diff --git a/sample-app/main.go b/sample-app/main.go index a1708f4..249fc3c 100644 --- a/sample-app/main.go +++ b/sample-app/main.go @@ -15,7 +15,7 @@ func workflow_example() { traceloop, err := tlp.NewClient(ctx, tlp.Config{ BaseURL: "api-staging.traceloop.com", - APIKey: os.Getenv("TRACELOOP_API_KEY"), + APIKey: os.Getenv("TRACELOOP_API_KEY"), }) defer func() { traceloop.Shutdown(ctx) }() @@ -24,7 +24,7 @@ func workflow_example() { return } - request, err := traceloop.GetOpenAIChatCompletionRequest("example-prompt", map[string]interface{}{ "date": time.Now().Format("01/02") }) + request, err := traceloop.GetOpenAIChatCompletionRequest("example-prompt", map[string]interface{}{"date": time.Now().Format("01/02")}) if err != nil { fmt.Printf("GetOpenAIChatCompletionRequest error: %v\n", err) return @@ -40,11 +40,11 @@ func workflow_example() { } llmSpan, err := traceloop.LogPrompt( - ctx, + ctx, tlp.Prompt{ - Vendor: "openai", - Mode: "chat", - Model: request.Model, + Vendor: "openai", + Mode: "chat", + Model: request.Model, Messages: promptMsgs, }, tlp.WorkflowAttributes{ @@ -79,11 +79,10 @@ func workflow_example() { Model: resp.Model, Messages: completionMsgs, }, tlp.Usage{ - TotalTokens: resp.Usage.TotalTokens, - CompletionTokens: resp.Usage.CompletionTokens, - PromptTokens: resp.Usage.PromptTokens, + TotalTokens: resp.Usage.TotalTokens, + CompletionTokens: resp.Usage.CompletionTokens, + PromptTokens: resp.Usage.PromptTokens, }) - fmt.Println(resp.Choices[0].Message.Content) } diff --git a/sample-app/workflow_example.go b/sample-app/workflow_example.go index 5022985..c48f2d1 100644 --- a/sample-app/workflow_example.go +++ b/sample-app/workflow_example.go @@ -15,7 +15,7 @@ func main() { traceloop, err := tlp.NewClient(ctx, tlp.Config{ BaseURL: "api-staging.traceloop.com", - APIKey: os.Getenv("TRACELOOP_API_KEY"), + APIKey: os.Getenv("TRACELOOP_API_KEY"), }) defer func() { traceloop.Shutdown(ctx) }() @@ -32,7 +32,7 @@ func main() { factGenTask := wf.NewTask("current_date_fact_generation") defer factGenTask.End() - request, err := traceloop.GetOpenAIChatCompletionRequest("example-prompt", map[string]interface{}{ "date": time.Now().Format("01/02") }) + request, err := traceloop.GetOpenAIChatCompletionRequest("example-prompt", map[string]interface{}{"date": time.Now().Format("01/02")}) if err != nil { fmt.Printf("GetOpenAIChatCompletionRequest error: %v\n", err) return @@ -49,9 +49,9 @@ func main() { llmSpan, err := factGenTask.LogPrompt( tlp.Prompt{ - Vendor: "openai", - Mode: "chat", - Model: request.Model, + Vendor: "openai", + Mode: "chat", + Model: request.Model, Messages: promptMsgs, }, ) @@ -83,9 +83,9 @@ func main() { Model: resp.Model, Messages: completionMsgs, }, tlp.Usage{ - TotalTokens: resp.Usage.TotalTokens, - CompletionTokens: resp.Usage.CompletionTokens, - PromptTokens: resp.Usage.PromptTokens, + TotalTokens: resp.Usage.TotalTokens, + CompletionTokens: resp.Usage.CompletionTokens, + PromptTokens: resp.Usage.PromptTokens, }) someOtherTask := wf.NewTask("some_other_task") @@ -94,7 +94,7 @@ func main() { otherPrompt, _ := someOtherTask.LogPrompt(tlp.Prompt{ Vendor: "openai", Mode: "chat", - Model: request.Model, + Model: request.Model, Messages: []tlp.Message{ { Index: 0, @@ -108,9 +108,9 @@ func main() { Model: resp.Model, Messages: completionMsgs, }, tlp.Usage{ - TotalTokens: resp.Usage.TotalTokens, - CompletionTokens: resp.Usage.CompletionTokens, - PromptTokens: resp.Usage.PromptTokens, + TotalTokens: resp.Usage.TotalTokens, + CompletionTokens: resp.Usage.CompletionTokens, + PromptTokens: resp.Usage.PromptTokens, }) fmt.Println(resp.Choices[0].Message.Content) diff --git a/semconv-ai/attributes.go b/semconv-ai/attributes.go index 4578fa2..78103c2 100644 --- a/semconv-ai/attributes.go +++ b/semconv-ai/attributes.go @@ -4,33 +4,33 @@ import "go.opentelemetry.io/otel/attribute" const ( // LLM - LLMVendor = attribute.Key("llm.vendor") - LLMRequestType = attribute.Key("llm.request.type") - LLMRequestModel = attribute.Key("llm.request.model") - LLMResponseModel = attribute.Key("llm.response.model") - LLMRequestMaxTokens = attribute.Key("llm.request.max_tokens") - LLMUsageTotalTokens = attribute.Key("llm.usage.total_tokens") - LLMUsageCompletionTokens = attribute.Key("llm.usage.completion_tokens") - LLMUsagePromptTokens = attribute.Key("llm.usage.prompt_tokens") - LLMTemperature = attribute.Key("llm.temperature") - LLMUser = attribute.Key("llm.user") - LLMHeaders = attribute.Key("llm.headers") - LLMTopP = attribute.Key("llm.top_p") - LLMTopK = attribute.Key("llm.top_k") - LLMFrequencyPenalty = attribute.Key("llm.frequency_penalty") - LLMPresencePenalty = attribute.Key("llm.presence_penalty") - LLMPrompts = attribute.Key("llm.prompts") - LLMCompletions = attribute.Key("llm.completions") - LLMChatStopSequence = attribute.Key("llm.chat.stop_sequences") - LLMRequestFunctions = attribute.Key("llm.request.functions") + LLMVendor = attribute.Key("llm.vendor") + LLMRequestType = attribute.Key("llm.request.type") + LLMRequestModel = attribute.Key("llm.request.model") + LLMResponseModel = attribute.Key("llm.response.model") + LLMRequestMaxTokens = attribute.Key("llm.request.max_tokens") + LLMUsageTotalTokens = attribute.Key("llm.usage.total_tokens") + LLMUsageCompletionTokens = attribute.Key("llm.usage.completion_tokens") + LLMUsagePromptTokens = attribute.Key("llm.usage.prompt_tokens") + LLMTemperature = attribute.Key("llm.temperature") + LLMUser = attribute.Key("llm.user") + LLMHeaders = attribute.Key("llm.headers") + LLMTopP = attribute.Key("llm.top_p") + LLMTopK = attribute.Key("llm.top_k") + LLMFrequencyPenalty = attribute.Key("llm.frequency_penalty") + LLMPresencePenalty = attribute.Key("llm.presence_penalty") + LLMPrompts = attribute.Key("llm.prompts") + LLMCompletions = attribute.Key("llm.completions") + LLMChatStopSequence = attribute.Key("llm.chat.stop_sequences") + LLMRequestFunctions = attribute.Key("llm.request.functions") - // Vector DB - VectorDBVendor = attribute.Key("vector_db.vendor") - VectorDBQueryTopK = attribute.Key("vector_db.query.top_k") + // Vector DB + VectorDBVendor = attribute.Key("vector_db.vendor") + VectorDBQueryTopK = attribute.Key("vector_db.query.top_k") - // LLM Workflows - TraceloopSpanKind = attribute.Key("traceloop.span.kind") - TraceloopWorkflowName = attribute.Key("traceloop.workflow.name") - TraceloopEntityName = attribute.Key("traceloop.entity.name") - TraceloopAssociationProperties = attribute.Key("traceloop.association.properties") -) \ No newline at end of file + // LLM Workflows + TraceloopSpanKind = attribute.Key("traceloop.span.kind") + TraceloopWorkflowName = attribute.Key("traceloop.workflow.name") + TraceloopEntityName = attribute.Key("traceloop.entity.name") + TraceloopAssociationProperties = attribute.Key("traceloop.association.properties") +) diff --git a/traceloop-sdk/config.go b/traceloop-sdk/config.go index 2cb6f90..e5e0a19 100644 --- a/traceloop-sdk/config.go +++ b/traceloop-sdk/config.go @@ -3,14 +3,14 @@ package traceloop import "time" type BackoffConfig struct { - MaxRetries uint64 + MaxRetries uint64 } type Config struct { - BaseURL string - APIKey string - TracerName string - ServiceName string - PollingInterval time.Duration - BackoffConfig BackoffConfig + BaseURL string + APIKey string + TracerName string + ServiceName string + PollingInterval time.Duration + BackoffConfig BackoffConfig } diff --git a/traceloop-sdk/model/prompt_registry.go b/traceloop-sdk/model/prompt_registry.go index 0f4b5ae..536a009 100644 --- a/traceloop-sdk/model/prompt_registry.go +++ b/traceloop-sdk/model/prompt_registry.go @@ -3,48 +3,48 @@ package model import "time" type ModelConfig struct { - Mode string `json:"mode"` - Model string `json:"model"` - Temperature float32 `json:"temperature"` - TopP float32 `json:"top_p"` - Stop []string `json:"stop"` - FrequencyPenalty float32 `json:"frequency_penalty"` - PresencePenalty float32 `json:"presence_penalty"` + Mode string `json:"mode"` + Model string `json:"model"` + Temperature float32 `json:"temperature"` + TopP float32 `json:"top_p"` + Stop []string `json:"stop"` + FrequencyPenalty float32 `json:"frequency_penalty"` + PresencePenalty float32 `json:"presence_penalty"` } type Message struct { - Index int `json:"index"` - Role string `json:"role"` - Template string `json:"template"` - Variables []string `json:"variables"` + Index int `json:"index"` + Role string `json:"role"` + Template string `json:"template"` + Variables []string `json:"variables"` } type PromptVersion struct { - Id string `json:"id"` - Hash string `json:"hash"` - Version uint `json:"version"` - Name string `json:"name"` - CreatedAt time.Time `json:"created_at"` - Provider string `json:"provider"` - TemplatingEngine string `json:"templating_engine"` - Messages []Message `json:"messages"` - LlmConfig ModelConfig `json:"llm_config"` + Id string `json:"id"` + Hash string `json:"hash"` + Version uint `json:"version"` + Name string `json:"name"` + CreatedAt time.Time `json:"created_at"` + Provider string `json:"provider"` + TemplatingEngine string `json:"templating_engine"` + Messages []Message `json:"messages"` + LlmConfig ModelConfig `json:"llm_config"` } type Target struct { - Id string `json:"id"` - PromptId string `json:"prompt_id"` - Version string `json:"version"` - UpdatedAt time.Time `json:"updated_at"` + Id string `json:"id"` + PromptId string `json:"prompt_id"` + Version string `json:"version"` + UpdatedAt time.Time `json:"updated_at"` } type Prompt struct { - Id string `json:"id"` - Versions []PromptVersion `json:"versions"` - Target Target `json:"target"` - Key string `json:"key"` - CreatedAt time.Time `json:"created_at"` - UpdatedAt time.Time `json:"updated_at"` + Id string `json:"id"` + Versions []PromptVersion `json:"versions"` + Target Target `json:"target"` + Key string `json:"key"` + CreatedAt time.Time `json:"created_at"` + UpdatedAt time.Time `json:"updated_at"` } -type PromptRegistry map[string]*Prompt \ No newline at end of file +type PromptRegistry map[string]*Prompt diff --git a/traceloop-sdk/prompt_registry.go b/traceloop-sdk/prompt_registry.go index 211f10c..669edeb 100644 --- a/traceloop-sdk/prompt_registry.go +++ b/traceloop-sdk/prompt_registry.go @@ -11,8 +11,8 @@ import ( ) type PromptsResponse struct { - Prompts []model.Prompt `json:"prompts"` - Environment string `json:"environment"` + Prompts []model.Prompt `json:"prompts"` + Environment string `json:"environment"` } func (instance *Traceloop) populatePromptRegistry() { @@ -38,7 +38,7 @@ func (instance *Traceloop) populatePromptRegistry() { func (instance *Traceloop) pollPrompts() { prompts := make(chan []model.Prompt) - errs := make(chan error) + errs := make(chan error) instance.populatePromptRegistry() @@ -103,12 +103,12 @@ func (instance *Traceloop) GetOpenAIChatCompletionRequest(key string, variables } return &openai.ChatCompletionRequest{ - Model: promptVersion.LlmConfig.Model, - Temperature: promptVersion.LlmConfig.Temperature, - TopP: promptVersion.LlmConfig.TopP, - Stop: promptVersion.LlmConfig.Stop, + Model: promptVersion.LlmConfig.Model, + Temperature: promptVersion.LlmConfig.Temperature, + TopP: promptVersion.LlmConfig.TopP, + Stop: promptVersion.LlmConfig.Stop, FrequencyPenalty: promptVersion.LlmConfig.FrequencyPenalty, - PresencePenalty: promptVersion.LlmConfig.PresencePenalty, - Messages: messages, + PresencePenalty: promptVersion.LlmConfig.PresencePenalty, + Messages: messages, }, nil -} \ No newline at end of file +} diff --git a/traceloop-sdk/sdk.go b/traceloop-sdk/sdk.go index b953f52..67ab77d 100644 --- a/traceloop-sdk/sdk.go +++ b/traceloop-sdk/sdk.go @@ -19,10 +19,10 @@ import ( const PromptsPath = "/v1/traceloop/prompts" type Traceloop struct { - config Config - promptRegistry model.PromptRegistry - tracerProvider *trace.TracerProvider - http.Client + config Config + promptRegistry model.PromptRegistry + tracerProvider *trace.TracerProvider + http.Client } type LLMSpan struct { @@ -47,7 +47,7 @@ func NewClient(ctx context.Context, config Config) (*Traceloop, error) { func (instance *Traceloop) initialize(ctx context.Context) error { if instance.config.BaseURL == "" { baseUrl := os.Getenv("TRACELOOP_BASE_URL") - if baseUrl == "" { + if baseUrl == "" { instance.config.BaseURL = "api.traceloop.com" } else { instance.config.BaseURL = baseUrl @@ -78,8 +78,8 @@ func setMessagesAttribute(span apitrace.Span, prefix string, messages []Message) for _, message := range messages { attrsPrefix := fmt.Sprintf("%s.%d", prefix, message.Index) span.SetAttributes( - attribute.String(attrsPrefix + ".content", message.Content), - attribute.String(attrsPrefix + ".role", message.Role), + attribute.String(attrsPrefix+".content", message.Content), + attribute.String(attrsPrefix+".role", message.Role), ) } } @@ -89,7 +89,7 @@ func (instance *Traceloop) tracerName() string { return instance.config.TracerName } else { return "traceloop.tracer" - } + } } func (instance *Traceloop) getTracer() apitrace.Tracer { @@ -99,7 +99,7 @@ func (instance *Traceloop) getTracer() apitrace.Tracer { func (instance *Traceloop) LogPrompt(ctx context.Context, prompt Prompt, workflowAttrs WorkflowAttributes) (LLMSpan, error) { spanName := fmt.Sprintf("%s.%s", prompt.Vendor, prompt.Mode) _, span := instance.getTracer().Start(ctx, spanName) - + span.SetAttributes( semconvai.LLMVendor.String(prompt.Vendor), semconvai.LLMRequestModel.String(prompt.Model), @@ -109,7 +109,7 @@ func (instance *Traceloop) LogPrompt(ctx context.Context, prompt Prompt, workflo setMessagesAttribute(span, "llm.prompts", prompt.Messages) - return LLMSpan{ + return LLMSpan{ span: span, }, nil } @@ -130,7 +130,7 @@ func (llmSpan *LLMSpan) LogCompletion(ctx context.Context, completion Completion } func (instance *Traceloop) Shutdown(ctx context.Context) { - if instance.tracerProvider != nil{ - instance.tracerProvider.Shutdown(ctx) + if instance.tracerProvider != nil { + instance.tracerProvider.Shutdown(ctx) } } diff --git a/traceloop-sdk/tracing.go b/traceloop-sdk/tracing.go index 9dd54fb..1c799ec 100644 --- a/traceloop-sdk/tracing.go +++ b/traceloop-sdk/tracing.go @@ -16,15 +16,15 @@ import ( func newTraceloopExporter(ctx context.Context, config Config) (*otlp.Exporter, error) { return otlp.New( - ctx, - otlphttp.NewClient( - otlphttp.WithEndpoint(config.BaseURL), - otlphttp.WithHeaders( - map[string]string{ - "Authorization": fmt.Sprintf("Bearer %s", config.APIKey), - }, - ), + ctx, + otlphttp.NewClient( + otlphttp.WithEndpoint(config.BaseURL), + otlphttp.WithHeaders( + map[string]string{ + "Authorization": fmt.Sprintf("Bearer %s", config.APIKey), + }, ), + ), ) } @@ -53,7 +53,7 @@ func newGenericExporter(ctx context.Context) (*otlp.Exporter, error) { ctx, otlphttp.NewClient( otlphttp.WithEndpoint(endpoint), - otlphttp.WithHeaders(headers), + otlphttp.WithHeaders(headers), ), ) } else if protocol == "grpc" { @@ -70,9 +70,8 @@ func newGenericExporter(ctx context.Context) (*otlp.Exporter, error) { } } - func newOtlpExporter(ctx context.Context, config Config) (*otlp.Exporter, error) { - if (os.Getenv("OTEL_EXPORTER_OTLP_ENDPOINT") == "") { + if os.Getenv("OTEL_EXPORTER_OTLP_ENDPOINT") == "" { return newTraceloopExporter(ctx, config) } else { return newGenericExporter(ctx) @@ -94,7 +93,7 @@ func resourceName(serviceName string) string { } return "unknown_service" -} +} func newTracerProvider(ctx context.Context, serviceName string, exp trace.SpanExporter) (*trace.TracerProvider, error) { r, err := resource.New( @@ -119,7 +118,7 @@ func (instance *Traceloop) initTracer(ctx context.Context, serviceName string) e if err != nil { return fmt.Errorf("create otlp exporter: %w", err) } - + tp, err := newTracerProvider(ctx, serviceName, exp) if err != nil { return fmt.Errorf("create tracer provider: %w", err) diff --git a/traceloop-sdk/tracing_types.go b/traceloop-sdk/tracing_types.go index 41f9960..a7b5ac9 100644 --- a/traceloop-sdk/tracing_types.go +++ b/traceloop-sdk/tracing_types.go @@ -1,35 +1,35 @@ package traceloop type Message struct { - Index int `json:"index"` - Role string `json:"role"` - Content string `json:"content"` + Index int `json:"index"` + Role string `json:"role"` + Content string `json:"content"` } type Prompt struct { - Vendor string `json:"vendor"` - Model string `json:"model"` - Mode string `json:"mode"` - Temperature float32 `json:"temperature"` - TopP float32 `json:"top_p"` - Stop []string `json:"stop"` - FrequencyPenalty float32 `json:"frequency_penalty"` - PresencePenalty float32 `json:"presence_penalty"` - Messages []Message `json:"messages"` + Vendor string `json:"vendor"` + Model string `json:"model"` + Mode string `json:"mode"` + Temperature float32 `json:"temperature"` + TopP float32 `json:"top_p"` + Stop []string `json:"stop"` + FrequencyPenalty float32 `json:"frequency_penalty"` + PresencePenalty float32 `json:"presence_penalty"` + Messages []Message `json:"messages"` } type Completion struct { - Model string `json:"model"` - Messages []Message `json:"messages"` + Model string `json:"model"` + Messages []Message `json:"messages"` } type WorkflowAttributes struct { - Name string `json:"workflow_name"` - AssociationProperties map[string]string `json:"association_properties"` + Name string `json:"workflow_name"` + AssociationProperties map[string]string `json:"association_properties"` } type Usage struct { - TotalTokens int `json:"total_tokens"` - CompletionTokens int `json:"completion_tokens"` - PromptTokens int `json:"prompt_tokens"` + TotalTokens int `json:"total_tokens"` + CompletionTokens int `json:"completion_tokens"` + PromptTokens int `json:"prompt_tokens"` } diff --git a/traceloop-sdk/utils.go b/traceloop-sdk/utils.go index 339c5cb..32d1c23 100644 --- a/traceloop-sdk/utils.go +++ b/traceloop-sdk/utils.go @@ -22,7 +22,7 @@ func (instance *Traceloop) fetchPath(path string) (*http.Response, error) { func (instance *Traceloop) fetchPathWithRetry(path string, maxRetries uint64) (*http.Response, error) { var resp *http.Response - + err := backoff.Retry(func() error { var err error resp, err = instance.fetchPath(path) @@ -33,4 +33,4 @@ func (instance *Traceloop) fetchPathWithRetry(path string, maxRetries uint64) (* }, backoff.WithMaxRetries(backoff.NewExponentialBackOff(), maxRetries)) return resp, err -} \ No newline at end of file +} diff --git a/traceloop-sdk/workflow.go b/traceloop-sdk/workflow.go index 11c7a50..501a03a 100644 --- a/traceloop-sdk/workflow.go +++ b/traceloop-sdk/workflow.go @@ -9,20 +9,20 @@ import ( ) type Workflow struct { - sdk *Traceloop - ctx context.Context - Attributes WorkflowAttributes `json:"workflow_attributes"` + sdk *Traceloop + ctx context.Context + Attributes WorkflowAttributes `json:"workflow_attributes"` } type Task struct { - workflow *Workflow - ctx context.Context - Name string `json:"name"` + workflow *Workflow + ctx context.Context + Name string `json:"name"` } func (instance *Traceloop) NewWorkflow(ctx context.Context, attrs WorkflowAttributes) *Workflow { wCtx, span := instance.getTracer().Start(ctx, fmt.Sprintf("%s.workflow", attrs.Name), trace.WithNewRoot()) - + span.SetAttributes( semconvai.TraceloopWorkflowName.String(attrs.Name), semconvai.TraceloopSpanKind.String("workflow"), @@ -30,8 +30,8 @@ func (instance *Traceloop) NewWorkflow(ctx context.Context, attrs WorkflowAttrib ) return &Workflow{ - sdk: instance, - ctx: wCtx, + sdk: instance, + ctx: wCtx, Attributes: attrs, } } @@ -55,8 +55,8 @@ func (workflow *Workflow) NewTask(name string) *Task { return &Task{ workflow: workflow, - ctx: tCtx, - Name: name, + ctx: tCtx, + Name: name, } }