Core tracer
When first starting out with Gentrace, we recommend that users use our provider wrappers for OpenAI and Pinecone to simplify the process of instrumenting their code.
However, if you want to trace arbitrary code (e.g. external API or database calls), we provide a tracer in our base SDKs.
Using measure()
to trace arbitrary code
Let's say we have code to create an embedding in OpenAI that is instrumented by Gentrace using the OpenAI provider wrapper.
Original code
- TypeScript
- Python
typescript
import {init ,Pipeline } from "@gentrace/core";import {initPlugin asinitOpenAIPlugin } from "@gentrace/openai";// This function globally initializes Gentrace with the appropriate// credentials. Constructors like Pipeline() will transparently use// these credentials to authenticate with Gentrace.init ({apiKey :process .env .GENTRACE_API_KEY });constopenaiPlugin = awaitinitOpenAIPlugin ({apiKey :process .env .OPENAI_KEY ,});constpipeline = newPipeline ({slug : "create-embedding",plugins : {openai :openaiPlugin ,pinecone :pineconePlugin },});construnner =pipeline .start ()constopenai =runner .openai ;constembeddingResponse = awaitopenai .embeddings .create ({model : 'text-embedding-ada-002',input : "Human, software engineer, Gentrace: Vivek",});awaitrunner .submit ();
python
import gentraceimport osgentrace.init(api_key=os.getenv("GENTRACE_API_KEY"))pipeline = gentrace.Pipeline(slug="create-embedding",openai_config={"api_key": os.getenv("OPENAI_KEY"),})runner = pipeline.start()openai = runner.get_openai()embedding_response = openai.Embedding.create(model="text-embedding-ada-002",input="Human, software engineer, Gentrace: Vivek");runner.submit()
Adjusted code
We now must modify this code to include a database call to retrieve a user's name before creating our embedding.
typescript
import {init ,Pipeline } from "@gentrace/core";import {initPlugin asinitOpenAIPlugin } from "@gentrace/openai";import {User } from "../models";// This function globally initializes Gentrace with the appropriate// credentials. Constructors like Pipeline() will transparently use// these credentials to authenticate with Gentrace.init ({apiKey :process .env .GENTRACE_API_KEY });constopenaiPlugin = awaitinitOpenAIPlugin ({apiKey :process .env .OPENAI_KEY ,});constpipeline = newPipeline ({slug : "create-embedding",plugins : {openai :openaiPlugin ,pinecone :pineconePlugin },});construnner =pipeline .start ()constopenai =runner .openai ;constuserId = "550e8400-e29b-41d4-a716-446655440000";constgentraceOrgId = "c9a646d3-9c61-4cb7-bfcd-ee2522c8f633";constname = awaitrunner .measure (async (userId ,gentraceOrgId ) => {// Custom application logicconstuser = awaitUser .findOne ({where : {id :userId ,orgId :gentraceOrgId ,}})returnuser .name },// Inputs must be passed via a dependency array, so Gentrace// can properly trace the data.[userId ,gentraceOrgId ],);constembeddingResponse = awaitopenai .embeddings .create ({model : 'text-embedding-ada-002',input : `Human, software engineer, Gentrace: ${name }`,});awaitrunner .submit ();
python
import gentraceimport osfrom app.models import Usergentrace.init(api_key=os.getenv("GENTRACE_API_KEY"))pipeline = gentrace.Pipeline(slug="create-embedding",openai_config={"api_key": os.getenv("OPENAI_KEY"),})runner = pipeline.start()user_id = "550e8400-e29b-41d4-a716-446655440000"org_id = "c9a646d3-9c61-4cb7-bfcd-ee2522c8f633"name = runner.measure(# Custom application logiclambda user_id, org_id: User.find_one({"id": user_id,"orgId": org_id,}),user_id=user_id,org_id=org_id)openai = runner.get_openai()embedding_response = openai.Embedding.create(model="text-embedding-ada-002",input="Human, software engineer, Gentrace: " + name);runner.submit()
In the above code example, the measure()
function allows us to trace arbitrary code. If you navigate to the Gentrace
UI, you will see that measured database call is now included in the trace.
Using checkpoint()
to trace arbitrary code
If you want more control over when to start and stop a trace, you can use the checkpoint()
function.
Rather than wrapping your desired logic in a measure()
callback, you specify a checkpoint()
invocation. The invocation
then constructs a duration relative to the last time checkpoint()
was invoked. You must also manually specify the exact
inputs/outputs for that checkpoint.
Adjusted code
typescript
import {init ,Pipeline } from "@gentrace/core";import {initPlugin asinitOpenAIPlugin } from "@gentrace/openai";import {User } from "../models";// This function globally initializes Gentrace with the appropriate// credentials. Constructors like Pipeline() will transparently use// these credentials to authenticate with Gentrace.init ({apiKey :process .env .GENTRACE_API_KEY });constopenaiPlugin = awaitinitOpenAIPlugin ({apiKey :process .env .OPENAI_KEY ,});constpipeline = newPipeline ({slug : "create-embedding",plugins : {openai :openaiPlugin ,pinecone :pineconePlugin },});construnner =pipeline .start ()constopenai =runner .openai ;constuserId = "550e8400-e29b-41d4-a716-446655440000";constgentraceOrgId = "c9a646d3-9c61-4cb7-bfcd-ee2522c8f633";// Custom application logicconstuser = awaitUser .findOne ({where : {id :userId ,orgId :gentraceOrgId ,}});constname =user .name ;runner .checkpoint ({inputs : {userId ,orgId :gentraceOrgId },outputs : {name }});constembeddingResponse = awaitopenai .embeddings .create ({model : 'text-embedding-ada-002',input : `Human, software engineer, Gentrace: ${name }!`,});awaitrunner .submit ();
python
import gentraceimport osfrom app.models import Usergentrace.init(api_key=os.getenv("GENTRACE_API_KEY"))pipeline = gentrace.Pipeline(slug="create-embedding",openai_config={"api_key": os.getenv("OPENAI_KEY"),})runner = pipeline.start()user_id = "550e8400-e29b-41d4-a716-446655440000"org_id = "c9a646d3-9c61-4cb7-bfcd-ee2522c8f633"# Custom application logicuser = User.find_one({"id": user_id,"orgId": org_id,}),name = user.namerunner.checkpoint({"inputs": {"user_id": user_id,"org_id": org_id,},"outputs": {"value": name}})openai = runner.get_openai()embedding_response = openai.Embedding.create(model="text-embedding-ada-002",input="Human, software engineer, Gentrace: " + name);runner.submit()
Evaluation
Gentrace also provides a way to evaluate generative pipelines that use measure()
or checkpoint()
invocations. You
can read more about that here.