In the previous section, we explored the quick integration of Maxim observability using decorators. However, there are scenarios where you might need finer control over your code's tracing. This section will guide you through the process of manually integrating Maxim observability into your codebase, providing you with more flexibility and granular control over your observability implementation.
from maxim.logger import TraceConfig
trace = logger.trace(TraceConfig( id = "trace-id" , name = "trace-name" , tags = { "key" : "value" }))
Creating a session and adding a trace to it from maxim.logger import SessionConfig, TraceConfig
session = logger.session(SessionConfig( id = "session-id" , name = "session-name" , tags = { "key" : "value" }))
trace = session.trace(TraceConfig( id = "trace-id" ))
Using custom ids allows you to fetch a trace in any function using the same id. This can be useful in updating trace across your workflow.
Using custom ids for Traces from maxim.logger.components.trace import TraceConfig
# ... in function 1
trace = logger.trace(TraceConfig( id = "trace-id" ))
# ... in function 2
trace = logger.trace(TraceConfig( id = "trace-id" ))
# it returns the same trace object
trace.add_tag({ "key" : "value" })
Using custom ids for Sessions # ... in function 1
session = logger.session(SessionConfig( id = "session-id" ))
# ... in function 2
session = logger.trace(SessionConfig( id = "session-id" ))
# it returns the same session object
session.add_tag({ "key" : "value" })
Once you have a Trace object, you can add
A Span (short for timespan), groups a bunch of items (Events, Retrieval, Generation, Feedback).
from maxim.logger import SpanConfig
span = trace.span(SpanConfig( id = str (uuid4()), name = "Test Span" ))
span.event( "event-id" , "event-name" )
span.end()
An event is a point in time when something happened in the system.
Adding an Event to a Trace trace.event( "event-id" , "event name" , {})
A Retrieval is a special type of Span in Maxim, which represents a retrieval query to a knowledge base or vector database.
Adding a retrieval to a span from maxim.logger import RetrievalConfig
retrieval = span.retrieval(RetrievalConfig( id = "retrieval-id" , name = "Test Retrieval" ))
retrieval.input( "How many PTO days do I have?" )
retrieval.output([ "doc1" , "doc2" ])
retrieval.end()
A Generation is a special type of Span in Maxim, which represents a call to an LLM.
generation.result
expects result to be in OpenAI response format. Here is the reference to the OpenAI response
format
Adding a Generation to a Span from maxim.logger import GenerationConfig
generationConfig = GenerationConfig(
id = str (uuid4()),
name = "gen1" ,
provider = "openai" ,
model = "gpt-3.5-turbo-16k" ,
model_parameters = { "temperature" : 3 },
messages = [{
"role" : "user" ,
"content" : "Hello, how can I help you today?"
}])
generation = trace.generation(generationConfig)
generation.result({
"id" : "cmpl-uN1k3lnZkTlZg8GHt4Vtd1aB" ,
"object" : "text_completion" ,
"created" : 1718393286 ,
"model" : "gpt-3.5-turbo-16k" ,
"choices" : [
{
"index" : 0 ,
"text" : " \n Here is the response \n " ,
"logprobs" : None ,
"finish_reason" : "stop" ,
},
],
"usage" : {
"prompt_tokens" : 7 ,
"completion_tokens" : 105 ,
"total_tokens" : 112 ,
},
})
A Feedback is a special type of event in Maxim, which is a point in time when Feedback was given in the system.
Adding a Feedback to a Trace from maxim.logger.components import Feedback
trace.feedback( feedback = Feedback( score = 5 , comment = "Great job!" ))