opik-langchain 1.0.0 → 1.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +113 -0
- package/dist/index.cjs +1 -0
- package/dist/index.d.cts +55 -0
- package/dist/index.d.ts +55 -0
- package/dist/index.js +1 -0
- package/package.json +11 -15
package/README.md
ADDED
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
# Opik LangChain Integration
|
|
2
|
+
|
|
3
|
+
[](https://www.npmjs.com/package/opik-langchain)
|
|
4
|
+
[](https://github.com/comet-ml/opik/blob/main/LICENSE)
|
|
5
|
+
|
|
6
|
+
Seamlessly integrate [Opik](https://www.comet.com/docs/opik/) observability with your [LangChain](https://js.langchain.com/) applications to trace, monitor, and debug your LLM chains, agents, and tools.
|
|
7
|
+
|
|
8
|
+
## Features
|
|
9
|
+
|
|
10
|
+
- 🔍 **Comprehensive Tracing**: Automatically trace LLM calls, chains, tools, retrievers, and agents
|
|
11
|
+
- 📊 **Hierarchical Visualization**: View your LangChain execution as a structured trace with parent-child relationships
|
|
12
|
+
- 📝 **Detailed Metadata Capture**: Record model names, prompts, completions, usage statistics, and custom metadata
|
|
13
|
+
- 🚨 **Error Handling**: Capture and visualize errors at every step of your LangChain execution
|
|
14
|
+
- 🏷️ **Custom Tagging**: Add custom tags to organize and filter your traces
|
|
15
|
+
|
|
16
|
+
## Installation
|
|
17
|
+
|
|
18
|
+
```bash
|
|
19
|
+
# npm
|
|
20
|
+
npm install opik-langchain
|
|
21
|
+
|
|
22
|
+
# yarn
|
|
23
|
+
yarn add opik-langchain
|
|
24
|
+
|
|
25
|
+
# pnpm
|
|
26
|
+
pnpm add opik-langchain
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
### Requirements
|
|
30
|
+
|
|
31
|
+
- Node.js ≥ 18
|
|
32
|
+
- LangChain (`@langchain/core` ≥ 0.3.42)
|
|
33
|
+
- Opik SDK (automatically installed as a dependency)
|
|
34
|
+
|
|
35
|
+
## Quick Start
|
|
36
|
+
|
|
37
|
+
```typescript
|
|
38
|
+
import { OpikCallbackHandler } from "opik-langchain";
|
|
39
|
+
import { ChatOpenAI } from "@langchain/openai";
|
|
40
|
+
|
|
41
|
+
// Create the Opik callback handler
|
|
42
|
+
const opikHandler = new OpikCallbackHandler();
|
|
43
|
+
|
|
44
|
+
// Create your LangChain components with the handler
|
|
45
|
+
const llm = new ChatOpenAI({
|
|
46
|
+
callbacks: [opikHandler],
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
// Run LLM
|
|
50
|
+
const response = await llm.invoke("Hello, how can you help me today?", {
|
|
51
|
+
callbacks: [opikHandler],
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
// Optionally, ensure all traces are sent before your app terminates
|
|
55
|
+
await opikHandler.flushAsync();
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
## Advanced Configuration
|
|
59
|
+
|
|
60
|
+
The `OpikCallbackHandler` constructor accepts the following options:
|
|
61
|
+
|
|
62
|
+
```typescript
|
|
63
|
+
interface OpikCallbackHandlerOptions {
|
|
64
|
+
// Optional array of tags to apply to all traces
|
|
65
|
+
tags?: string[];
|
|
66
|
+
|
|
67
|
+
// Optional metadata to include with all traces
|
|
68
|
+
metadata?: Record<string, unknown>;
|
|
69
|
+
|
|
70
|
+
// Optional project name for Opik
|
|
71
|
+
projectName?: string;
|
|
72
|
+
|
|
73
|
+
// Optional pre-configured Opik client
|
|
74
|
+
client?: Opik;
|
|
75
|
+
}
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
### Capturing Custom Metadata
|
|
79
|
+
|
|
80
|
+
You can pass custom metadata when invoking your chains:
|
|
81
|
+
|
|
82
|
+
```typescript
|
|
83
|
+
const response = await chain.invoke(
|
|
84
|
+
{ input: "Tell me about AI" },
|
|
85
|
+
{
|
|
86
|
+
callbacks: [opikHandler],
|
|
87
|
+
metadata: {
|
|
88
|
+
userId: "user-123",
|
|
89
|
+
sessionId: "session-456",
|
|
90
|
+
requestId: "req-789",
|
|
91
|
+
},
|
|
92
|
+
}
|
|
93
|
+
);
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
## Viewing Traces
|
|
97
|
+
|
|
98
|
+
To view your traces:
|
|
99
|
+
|
|
100
|
+
1. Sign in to your [Comet account](https://www.comet.com/signin)
|
|
101
|
+
2. Navigate to the Opik section
|
|
102
|
+
3. Select your project to view all traces
|
|
103
|
+
4. Click on a specific trace to see the detailed execution flow
|
|
104
|
+
|
|
105
|
+
## Learn More
|
|
106
|
+
|
|
107
|
+
- [Opik Documentation](https://www.comet.com/docs/opik/)
|
|
108
|
+
- [LangChain Documentation](https://js.langchain.com/)
|
|
109
|
+
- [Opik TypeScript SDK](https://github.com/comet-ml/opik/tree/main/sdks/typescript)
|
|
110
|
+
|
|
111
|
+
## License
|
|
112
|
+
|
|
113
|
+
Apache 2.0
|
package/dist/index.cjs
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
'use strict';var base=require('@langchain/core/callbacks/base'),opik=require('opik'),messages=require('@langchain/core/messages');var f=r=>typeof r=="object"&&r!==null,j=r=>f(r)&&"content"in r,V=r=>f(r)&&"messages"in r,x=r=>f(r)&&"value"in r,z=r=>f(r)&&"kwargs"in r,k=(...r)=>r.find(e=>e!=null),_=r=>Object.fromEntries(Object.entries(r).filter(([,e])=>!(e==null||Array.isArray(e)&&e.length===0||f(e)&&Object.keys(e).length===0))),M=r=>{try{return JSON.parse(r)}catch{return {value:r}}},R=r=>{var s;let e=(s=r.name)!=null?s:r.getType();r.getType()==="human"?e="user":r.getType()==="ai"?e="assistant":r.getType()==="system"&&(e="system");let n={},t=r;return "tool_calls"in t&&(n.tool_calls=t.tool_calls),"status"in t&&(n.status=t.status),"artifact"in t&&(n.artifact=t.artifact),_({content:r.content,role:e,...n})},$=r=>({messages:r.flatMap(n=>n.map(R))}),S=r=>"message"in r?R(r.message):"text"in r&&r.text?r.text:r,E=r=>({generations:r.flatMap(n=>Array.isArray(n)?n.map(S):S(n))}),A=r=>r instanceof messages.ToolMessage?R(r):void 0,y=(r,e,n)=>{let t=_({model:k(e==null?void 0:e.model,n==null?void 0:n.ls_model_name,r.name),temperature:k(e==null?void 0:e.temperature,n==null?void 0:n.ls_temperature),top_p:k(e==null?void 0:e.top_p,e==null?void 0:e.topP),top_k:k(e==null?void 0:e.top_k,e==null?void 0:e.topK),max_tokens:k(e==null?void 0:e.max_tokens,e==null?void 0:e.maxOutputTokens),frequency_penalty:e==null?void 0:e.frequency_penalty,presence_penalty:e==null?void 0:e.presence_penalty,response_format:e==null?void 0:e.response_format,tool_choice:e==null?void 0:e.tool_choice,function_call:e==null?void 0:e.function_call,n:e==null?void 0:e.n,stop:k(e==null?void 0:e.stop,e==null?void 0:e.stop_sequence)});return Object.keys(t).length?t:e},T=r=>{if(r==null)return {value:r};if(typeof r=="string"||typeof r=="number"||typeof r=="boolean")return {value:r};if(!f(r))return {value:r};if(j(r)&&r.content!==void 0){let e=r.content;return f(e)?e:{value:e}}if(V(r)&&r.messages!==void 0)return {messages:Array.isArray(r.messages)?r.messages.map(T):[T(r.messages)]};if(x(r)&&r.value!==void 0){let e=r.value;return f(e)?e:{value:e}}return z(r)&&r.kwargs!==void 0?T(r.kwargs):Object.fromEntries(Object.entries(r).map(([e,n])=>[e,T(n)]))},L=r=>{try{let e=(Array.isArray(r)?r:[r]).filter(n=>n!=null).flatMap(T);return e.length===1?e[0]:e.length>1?{values:e}:{}}catch(e){return console.warn("Error processing chain outputs:",e),{error:String(e)}}},C=r=>{try{let e=(Array.isArray(r)?r:[r]).filter(n=>n!=null).flatMap(T);return e.length===1?e[0]:e.length>1?{values:e}:{}}catch(e){return console.warn("Error processing chain inputs:",e),{error:String(e)}}};var b=class extends base.BaseCallbackHandler{constructor(n){var t;super();this.name="OpikCallbackHandler";this.spansMap=new Map;this.options={...n},this.client=(t=n==null?void 0:n.client)!=null?t:new opik.Opik,n!=null&&n.projectName&&(this.client.config.projectName=n==null?void 0:n.projectName);}startTracing({runId:n,parentRunId:t,name:s,input:i,tags:o,metadata:l,type:d}){let g=l==null?void 0:l.ls_provider,p=l==null?void 0:l.ls_model_name;if(!t&&n===this.rootTraceId)return;if(t||(this.rootTraceId=n,this.rootTrace=this.client.trace({name:s,input:i,tags:this.options.tags,metadata:l})),!this.rootTrace){opik.logger.debug(`handleChainStart error ${n} has no parent`);return}let c;this.rootTraceId&&this.rootTraceId!==t&&(c=t);let h=this.spansMap.get(n),a;h?a=h.update({input:C(i),tags:o,metadata:l,model:p,provider:g}):a=this.rootTrace.span({type:d||opik.OpikSpanType.General,name:s,input:C(i),tags:o,metadata:l,model:p,provider:g,parentSpanId:c}),this.spansMap.set(n,a);}endTracing({runId:n,output:t,error:s,tags:i,usage:o,metadata:l}){var p,c,h;let d;s&&(opik.logger.debug(`End tracing because of error ${s.message}`),d={message:s.message,exceptionType:s.name,traceback:(p=s.stack)!=null?p:""});let g=this.spansMap.get(n);if(!g){opik.logger.debug(`handleChainEnd span ${n} has not found`);return}g.update({output:t,errorInfo:d,tags:i,usage:o,metadata:l}),g.end(),this.spansMap.delete(n),n===this.rootTraceId&&((c=this.rootTrace)==null||c.update({output:t}),this.rootTraceId=void 0,(h=this.rootTrace)==null||h.end(),this.rootTrace=void 0);}async handleChatModelStart(n,t,s,i,o,l,d,g){var p,c,h;opik.logger.debug(`handleChatModelStart runId - ${s}, parentRunId ${i}`),this.startTracing({runId:s,parentRunId:i,name:(c=g!=null?g:(p=n.id.at(-1))==null?void 0:p.toString())!=null?c:"Chat Model",type:opik.OpikSpanType.Llm,input:$(t),tags:l,metadata:{...d,...y(n,(o==null?void 0:o.invocation_params)||{},d),tools:(h=o==null?void 0:o.invocation_params)==null?void 0:h.tools}});}async handleLLMStart(n,t,s,i,o,l,d,g){var p,c;opik.logger.debug(`handleLLMStart runId - ${s}, parentRunId ${i}`),this.startTracing({runId:s,parentRunId:i,name:(c=g!=null?g:(p=n.id.at(-1))==null?void 0:p.toString())!=null?c:"LLM",type:opik.OpikSpanType.Llm,input:{prompts:t},tags:l,metadata:{...d,...y(n,(o==null?void 0:o.invocation_params)||{},d)}});}async handleLLMError(n,t,s,i){opik.logger.debug(`handleLLMError runId - ${t}, parentRunId ${s}`),this.endTracing({runId:t,error:n,tags:i});}async handleLLMEnd(n,t,s,i){opik.logger.debug(`handleLLMEnd runId - ${t}, parentRunId ${s}`);let{llmOutput:o,generations:l,...d}=n,g=(o==null?void 0:o.tokenUsage)||(o==null?void 0:o.estimatedTokens)||{};this.endTracing({runId:t,output:E(l),usage:{prompt_tokens:g.completionTokens,completion_tokens:g.promptTokens,total_tokens:g.totalTokens},tags:i,metadata:d});}async handleChainStart(n,t,s,i,o,l,d,g){var h,a;if(opik.logger.debug(`handleChainStart runId - ${s}, parentRunId ${i}`),o!=null&&o.includes("langsmith:hidden"))return;let p=(a=g!=null?g:(h=n.id.at(-1))==null?void 0:h.toString())!=null?a:"Chain",c={runId:s,parentRunId:i,name:p,input:C(t),tags:this.options.tags,metadata:{...l,...y(n,{},l)}};i||(c.metadata={...l,...this.options.metadata}),this.startTracing(c);}async handleChainError(n,t,s,i){opik.logger.debug(`handleChainError runId - ${t}, parentRunId ${s}`),this.endTracing({runId:t,tags:i,error:n});}async handleChainEnd(n,t,s,i){opik.logger.debug(`handleChainEnd runId - ${t}, parentRunId ${s}`),this.endTracing({runId:t,output:L(n),tags:i});}async handleToolStart(n,t,s,i,o,l,d){var g,p;opik.logger.debug(`handleToolStart runId - ${s}, parentRunId ${i}`),this.startTracing({runId:s,parentRunId:i,name:(p=d!=null?d:(g=n.id.at(-1))==null?void 0:g.toString())!=null?p:"Tool",input:M(t),tags:o,type:opik.OpikSpanType.Tool,metadata:{...l,...y(n,{},l)}});}async handleToolError(n,t,s,i){opik.logger.debug(`handleToolError runId - ${t}, parentRunId ${s}`),this.endTracing({runId:t,tags:i,error:n});}async handleToolEnd(n,t,s,i){opik.logger.debug(`handleToolEnd runId - ${t}, parentRunId ${s}`),this.endTracing({runId:t,output:A(n),tags:i});}async handleAgentAction(n,t,s,i){opik.logger.debug(`handleAgentAction runId - ${t}, parentRunId ${s}`),this.startTracing({runId:t,parentRunId:s,name:n.tool,input:n,tags:i});}async handleAgentEnd(n,t,s,i){opik.logger.debug(`handleAgentEnd runId - ${t}, parentRunId ${s}`),this.endTracing({runId:t,output:n,tags:i});}async handleRetrieverStart(n,t,s,i,o,l,d){var g,p;opik.logger.debug(`handleRetrieverStart runId - ${s}, parentRunId ${i}`),this.startTracing({runId:s,parentRunId:i,name:(p=d!=null?d:(g=n.id.at(-1))==null?void 0:g.toString())!=null?p:"Retriever",type:opik.OpikSpanType.Tool,input:{query:t},tags:o,metadata:{...l,...y(n,{},l)}});}async handleRetrieverEnd(n,t,s,i){opik.logger.debug(`handleRetrieverEnd runId - ${t}, parentRunId ${s}`),this.endTracing({runId:t,output:{documents:n},tags:i});}async handleRetrieverError(n,t,s,i){opik.logger.debug(`handleRetrieverError runId - ${t}, parentRunId ${s}`),this.endTracing({runId:t,error:n,tags:i});}async flushAsync(){return this.client.flush()}};exports.OpikCallbackHandler=b;
|
package/dist/index.d.cts
ADDED
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { BaseCallbackHandler, BaseCallbackHandlerInput } from '@langchain/core/callbacks/base';
|
|
2
|
+
import { Serialized } from '@langchain/core/load/serializable';
|
|
3
|
+
import { ChainValues } from '@langchain/core/utils/types';
|
|
4
|
+
import { Opik } from 'opik';
|
|
5
|
+
import { RunnableConfig } from '@langchain/core/runnables';
|
|
6
|
+
import { LLMResult, ChatResult } from '@langchain/core/outputs';
|
|
7
|
+
import { BaseMessage } from '@langchain/core/messages';
|
|
8
|
+
import { AgentAction, AgentFinish } from '@langchain/core/agents';
|
|
9
|
+
|
|
10
|
+
type JsonNode = Record<string, unknown>;
|
|
11
|
+
interface OpikCallbackHandlerOptions {
|
|
12
|
+
tags?: [];
|
|
13
|
+
metadata?: JsonNode;
|
|
14
|
+
projectName?: string;
|
|
15
|
+
client?: Opik;
|
|
16
|
+
}
|
|
17
|
+
declare class OpikCallbackHandler extends BaseCallbackHandler implements BaseCallbackHandlerInput {
|
|
18
|
+
name: string;
|
|
19
|
+
private options;
|
|
20
|
+
private client;
|
|
21
|
+
private rootTraceId?;
|
|
22
|
+
private rootTrace?;
|
|
23
|
+
private spansMap;
|
|
24
|
+
constructor(options?: Partial<OpikCallbackHandlerOptions>);
|
|
25
|
+
private startTracing;
|
|
26
|
+
private endTracing;
|
|
27
|
+
handleChatModelStart(llm: Serialized, messages: BaseMessage[][], runId: string, parentRunId?: string, extraParams?: {
|
|
28
|
+
options: RunnableConfig;
|
|
29
|
+
invocation_params?: Record<string, unknown>;
|
|
30
|
+
batch_size: number;
|
|
31
|
+
cache?: boolean;
|
|
32
|
+
}, tags?: string[], metadata?: Record<string, unknown>, runName?: string): Promise<void>;
|
|
33
|
+
handleLLMStart(llm: Serialized, prompts: string[], runId: string, parentRunId?: string, extraParams?: {
|
|
34
|
+
options: RunnableConfig;
|
|
35
|
+
invocation_params?: Record<string, unknown>;
|
|
36
|
+
batch_size: number;
|
|
37
|
+
cache?: boolean;
|
|
38
|
+
}, tags?: string[], metadata?: Record<string, unknown>, runName?: string): Promise<void>;
|
|
39
|
+
handleLLMError(error: Error, runId: string, parentRunId?: string, tags?: string[]): Promise<void>;
|
|
40
|
+
handleLLMEnd(output: LLMResult | ChatResult, runId: string, parentRunId?: string, tags?: string[]): Promise<void>;
|
|
41
|
+
handleChainStart(chain: Serialized, input: ChainValues, runId: string, parentRunId?: string, tags?: string[], metadata?: Record<string, unknown>, runType?: string, runName?: string): Promise<void>;
|
|
42
|
+
handleChainError(error: Error, runId: string, parentRunId?: string, tags?: string[]): Promise<void>;
|
|
43
|
+
handleChainEnd(output: ChainValues, runId: string, parentRunId?: string, tags?: string[]): Promise<void>;
|
|
44
|
+
handleToolStart(tool: Serialized, input: string, runId: string, parentRunId?: string, tags?: string[], metadata?: Record<string, unknown>, runName?: string): Promise<void>;
|
|
45
|
+
handleToolError(error: Error, runId: string, parentRunId?: string, tags?: string[]): Promise<void>;
|
|
46
|
+
handleToolEnd(output: unknown, runId: string, parentRunId?: string, tags?: string[]): Promise<void>;
|
|
47
|
+
handleAgentAction(action: AgentAction, runId: string, parentRunId?: string, tags?: string[]): Promise<void>;
|
|
48
|
+
handleAgentEnd(action: AgentFinish, runId: string, parentRunId?: string, tags?: string[]): Promise<void>;
|
|
49
|
+
handleRetrieverStart(retriever: Serialized, query: string, runId: string, parentRunId?: string, tags?: string[], metadata?: Record<string, unknown>, name?: string): Promise<void>;
|
|
50
|
+
handleRetrieverEnd(documents: unknown[], runId: string, parentRunId?: string, tags?: string[]): Promise<void>;
|
|
51
|
+
handleRetrieverError(error: Error, runId: string, parentRunId?: string, tags?: string[]): Promise<void>;
|
|
52
|
+
flushAsync(): Promise<void>;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
export { OpikCallbackHandler };
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { BaseCallbackHandler, BaseCallbackHandlerInput } from '@langchain/core/callbacks/base';
|
|
2
|
+
import { Serialized } from '@langchain/core/load/serializable';
|
|
3
|
+
import { ChainValues } from '@langchain/core/utils/types';
|
|
4
|
+
import { Opik } from 'opik';
|
|
5
|
+
import { RunnableConfig } from '@langchain/core/runnables';
|
|
6
|
+
import { LLMResult, ChatResult } from '@langchain/core/outputs';
|
|
7
|
+
import { BaseMessage } from '@langchain/core/messages';
|
|
8
|
+
import { AgentAction, AgentFinish } from '@langchain/core/agents';
|
|
9
|
+
|
|
10
|
+
type JsonNode = Record<string, unknown>;
|
|
11
|
+
interface OpikCallbackHandlerOptions {
|
|
12
|
+
tags?: [];
|
|
13
|
+
metadata?: JsonNode;
|
|
14
|
+
projectName?: string;
|
|
15
|
+
client?: Opik;
|
|
16
|
+
}
|
|
17
|
+
declare class OpikCallbackHandler extends BaseCallbackHandler implements BaseCallbackHandlerInput {
|
|
18
|
+
name: string;
|
|
19
|
+
private options;
|
|
20
|
+
private client;
|
|
21
|
+
private rootTraceId?;
|
|
22
|
+
private rootTrace?;
|
|
23
|
+
private spansMap;
|
|
24
|
+
constructor(options?: Partial<OpikCallbackHandlerOptions>);
|
|
25
|
+
private startTracing;
|
|
26
|
+
private endTracing;
|
|
27
|
+
handleChatModelStart(llm: Serialized, messages: BaseMessage[][], runId: string, parentRunId?: string, extraParams?: {
|
|
28
|
+
options: RunnableConfig;
|
|
29
|
+
invocation_params?: Record<string, unknown>;
|
|
30
|
+
batch_size: number;
|
|
31
|
+
cache?: boolean;
|
|
32
|
+
}, tags?: string[], metadata?: Record<string, unknown>, runName?: string): Promise<void>;
|
|
33
|
+
handleLLMStart(llm: Serialized, prompts: string[], runId: string, parentRunId?: string, extraParams?: {
|
|
34
|
+
options: RunnableConfig;
|
|
35
|
+
invocation_params?: Record<string, unknown>;
|
|
36
|
+
batch_size: number;
|
|
37
|
+
cache?: boolean;
|
|
38
|
+
}, tags?: string[], metadata?: Record<string, unknown>, runName?: string): Promise<void>;
|
|
39
|
+
handleLLMError(error: Error, runId: string, parentRunId?: string, tags?: string[]): Promise<void>;
|
|
40
|
+
handleLLMEnd(output: LLMResult | ChatResult, runId: string, parentRunId?: string, tags?: string[]): Promise<void>;
|
|
41
|
+
handleChainStart(chain: Serialized, input: ChainValues, runId: string, parentRunId?: string, tags?: string[], metadata?: Record<string, unknown>, runType?: string, runName?: string): Promise<void>;
|
|
42
|
+
handleChainError(error: Error, runId: string, parentRunId?: string, tags?: string[]): Promise<void>;
|
|
43
|
+
handleChainEnd(output: ChainValues, runId: string, parentRunId?: string, tags?: string[]): Promise<void>;
|
|
44
|
+
handleToolStart(tool: Serialized, input: string, runId: string, parentRunId?: string, tags?: string[], metadata?: Record<string, unknown>, runName?: string): Promise<void>;
|
|
45
|
+
handleToolError(error: Error, runId: string, parentRunId?: string, tags?: string[]): Promise<void>;
|
|
46
|
+
handleToolEnd(output: unknown, runId: string, parentRunId?: string, tags?: string[]): Promise<void>;
|
|
47
|
+
handleAgentAction(action: AgentAction, runId: string, parentRunId?: string, tags?: string[]): Promise<void>;
|
|
48
|
+
handleAgentEnd(action: AgentFinish, runId: string, parentRunId?: string, tags?: string[]): Promise<void>;
|
|
49
|
+
handleRetrieverStart(retriever: Serialized, query: string, runId: string, parentRunId?: string, tags?: string[], metadata?: Record<string, unknown>, name?: string): Promise<void>;
|
|
50
|
+
handleRetrieverEnd(documents: unknown[], runId: string, parentRunId?: string, tags?: string[]): Promise<void>;
|
|
51
|
+
handleRetrieverError(error: Error, runId: string, parentRunId?: string, tags?: string[]): Promise<void>;
|
|
52
|
+
flushAsync(): Promise<void>;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
export { OpikCallbackHandler };
|
package/dist/index.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import {BaseCallbackHandler}from'@langchain/core/callbacks/base';import {Opik,logger,OpikSpanType}from'opik';import {ToolMessage}from'@langchain/core/messages';var f=r=>typeof r=="object"&&r!==null,j=r=>f(r)&&"content"in r,V=r=>f(r)&&"messages"in r,x=r=>f(r)&&"value"in r,z=r=>f(r)&&"kwargs"in r,k=(...r)=>r.find(e=>e!=null),_=r=>Object.fromEntries(Object.entries(r).filter(([,e])=>!(e==null||Array.isArray(e)&&e.length===0||f(e)&&Object.keys(e).length===0))),M=r=>{try{return JSON.parse(r)}catch{return {value:r}}},R=r=>{var s;let e=(s=r.name)!=null?s:r.getType();r.getType()==="human"?e="user":r.getType()==="ai"?e="assistant":r.getType()==="system"&&(e="system");let n={},t=r;return "tool_calls"in t&&(n.tool_calls=t.tool_calls),"status"in t&&(n.status=t.status),"artifact"in t&&(n.artifact=t.artifact),_({content:r.content,role:e,...n})},$=r=>({messages:r.flatMap(n=>n.map(R))}),S=r=>"message"in r?R(r.message):"text"in r&&r.text?r.text:r,E=r=>({generations:r.flatMap(n=>Array.isArray(n)?n.map(S):S(n))}),A=r=>r instanceof ToolMessage?R(r):void 0,y=(r,e,n)=>{let t=_({model:k(e==null?void 0:e.model,n==null?void 0:n.ls_model_name,r.name),temperature:k(e==null?void 0:e.temperature,n==null?void 0:n.ls_temperature),top_p:k(e==null?void 0:e.top_p,e==null?void 0:e.topP),top_k:k(e==null?void 0:e.top_k,e==null?void 0:e.topK),max_tokens:k(e==null?void 0:e.max_tokens,e==null?void 0:e.maxOutputTokens),frequency_penalty:e==null?void 0:e.frequency_penalty,presence_penalty:e==null?void 0:e.presence_penalty,response_format:e==null?void 0:e.response_format,tool_choice:e==null?void 0:e.tool_choice,function_call:e==null?void 0:e.function_call,n:e==null?void 0:e.n,stop:k(e==null?void 0:e.stop,e==null?void 0:e.stop_sequence)});return Object.keys(t).length?t:e},T=r=>{if(r==null)return {value:r};if(typeof r=="string"||typeof r=="number"||typeof r=="boolean")return {value:r};if(!f(r))return {value:r};if(j(r)&&r.content!==void 0){let e=r.content;return f(e)?e:{value:e}}if(V(r)&&r.messages!==void 0)return {messages:Array.isArray(r.messages)?r.messages.map(T):[T(r.messages)]};if(x(r)&&r.value!==void 0){let e=r.value;return f(e)?e:{value:e}}return z(r)&&r.kwargs!==void 0?T(r.kwargs):Object.fromEntries(Object.entries(r).map(([e,n])=>[e,T(n)]))},L=r=>{try{let e=(Array.isArray(r)?r:[r]).filter(n=>n!=null).flatMap(T);return e.length===1?e[0]:e.length>1?{values:e}:{}}catch(e){return console.warn("Error processing chain outputs:",e),{error:String(e)}}},C=r=>{try{let e=(Array.isArray(r)?r:[r]).filter(n=>n!=null).flatMap(T);return e.length===1?e[0]:e.length>1?{values:e}:{}}catch(e){return console.warn("Error processing chain inputs:",e),{error:String(e)}}};var b=class extends BaseCallbackHandler{constructor(n){var t;super();this.name="OpikCallbackHandler";this.spansMap=new Map;this.options={...n},this.client=(t=n==null?void 0:n.client)!=null?t:new Opik,n!=null&&n.projectName&&(this.client.config.projectName=n==null?void 0:n.projectName);}startTracing({runId:n,parentRunId:t,name:s,input:i,tags:o,metadata:l,type:d}){let g=l==null?void 0:l.ls_provider,p=l==null?void 0:l.ls_model_name;if(!t&&n===this.rootTraceId)return;if(t||(this.rootTraceId=n,this.rootTrace=this.client.trace({name:s,input:i,tags:this.options.tags,metadata:l})),!this.rootTrace){logger.debug(`handleChainStart error ${n} has no parent`);return}let c;this.rootTraceId&&this.rootTraceId!==t&&(c=t);let h=this.spansMap.get(n),a;h?a=h.update({input:C(i),tags:o,metadata:l,model:p,provider:g}):a=this.rootTrace.span({type:d||OpikSpanType.General,name:s,input:C(i),tags:o,metadata:l,model:p,provider:g,parentSpanId:c}),this.spansMap.set(n,a);}endTracing({runId:n,output:t,error:s,tags:i,usage:o,metadata:l}){var p,c,h;let d;s&&(logger.debug(`End tracing because of error ${s.message}`),d={message:s.message,exceptionType:s.name,traceback:(p=s.stack)!=null?p:""});let g=this.spansMap.get(n);if(!g){logger.debug(`handleChainEnd span ${n} has not found`);return}g.update({output:t,errorInfo:d,tags:i,usage:o,metadata:l}),g.end(),this.spansMap.delete(n),n===this.rootTraceId&&((c=this.rootTrace)==null||c.update({output:t}),this.rootTraceId=void 0,(h=this.rootTrace)==null||h.end(),this.rootTrace=void 0);}async handleChatModelStart(n,t,s,i,o,l,d,g){var p,c,h;logger.debug(`handleChatModelStart runId - ${s}, parentRunId ${i}`),this.startTracing({runId:s,parentRunId:i,name:(c=g!=null?g:(p=n.id.at(-1))==null?void 0:p.toString())!=null?c:"Chat Model",type:OpikSpanType.Llm,input:$(t),tags:l,metadata:{...d,...y(n,(o==null?void 0:o.invocation_params)||{},d),tools:(h=o==null?void 0:o.invocation_params)==null?void 0:h.tools}});}async handleLLMStart(n,t,s,i,o,l,d,g){var p,c;logger.debug(`handleLLMStart runId - ${s}, parentRunId ${i}`),this.startTracing({runId:s,parentRunId:i,name:(c=g!=null?g:(p=n.id.at(-1))==null?void 0:p.toString())!=null?c:"LLM",type:OpikSpanType.Llm,input:{prompts:t},tags:l,metadata:{...d,...y(n,(o==null?void 0:o.invocation_params)||{},d)}});}async handleLLMError(n,t,s,i){logger.debug(`handleLLMError runId - ${t}, parentRunId ${s}`),this.endTracing({runId:t,error:n,tags:i});}async handleLLMEnd(n,t,s,i){logger.debug(`handleLLMEnd runId - ${t}, parentRunId ${s}`);let{llmOutput:o,generations:l,...d}=n,g=(o==null?void 0:o.tokenUsage)||(o==null?void 0:o.estimatedTokens)||{};this.endTracing({runId:t,output:E(l),usage:{prompt_tokens:g.completionTokens,completion_tokens:g.promptTokens,total_tokens:g.totalTokens},tags:i,metadata:d});}async handleChainStart(n,t,s,i,o,l,d,g){var h,a;if(logger.debug(`handleChainStart runId - ${s}, parentRunId ${i}`),o!=null&&o.includes("langsmith:hidden"))return;let p=(a=g!=null?g:(h=n.id.at(-1))==null?void 0:h.toString())!=null?a:"Chain",c={runId:s,parentRunId:i,name:p,input:C(t),tags:this.options.tags,metadata:{...l,...y(n,{},l)}};i||(c.metadata={...l,...this.options.metadata}),this.startTracing(c);}async handleChainError(n,t,s,i){logger.debug(`handleChainError runId - ${t}, parentRunId ${s}`),this.endTracing({runId:t,tags:i,error:n});}async handleChainEnd(n,t,s,i){logger.debug(`handleChainEnd runId - ${t}, parentRunId ${s}`),this.endTracing({runId:t,output:L(n),tags:i});}async handleToolStart(n,t,s,i,o,l,d){var g,p;logger.debug(`handleToolStart runId - ${s}, parentRunId ${i}`),this.startTracing({runId:s,parentRunId:i,name:(p=d!=null?d:(g=n.id.at(-1))==null?void 0:g.toString())!=null?p:"Tool",input:M(t),tags:o,type:OpikSpanType.Tool,metadata:{...l,...y(n,{},l)}});}async handleToolError(n,t,s,i){logger.debug(`handleToolError runId - ${t}, parentRunId ${s}`),this.endTracing({runId:t,tags:i,error:n});}async handleToolEnd(n,t,s,i){logger.debug(`handleToolEnd runId - ${t}, parentRunId ${s}`),this.endTracing({runId:t,output:A(n),tags:i});}async handleAgentAction(n,t,s,i){logger.debug(`handleAgentAction runId - ${t}, parentRunId ${s}`),this.startTracing({runId:t,parentRunId:s,name:n.tool,input:n,tags:i});}async handleAgentEnd(n,t,s,i){logger.debug(`handleAgentEnd runId - ${t}, parentRunId ${s}`),this.endTracing({runId:t,output:n,tags:i});}async handleRetrieverStart(n,t,s,i,o,l,d){var g,p;logger.debug(`handleRetrieverStart runId - ${s}, parentRunId ${i}`),this.startTracing({runId:s,parentRunId:i,name:(p=d!=null?d:(g=n.id.at(-1))==null?void 0:g.toString())!=null?p:"Retriever",type:OpikSpanType.Tool,input:{query:t},tags:o,metadata:{...l,...y(n,{},l)}});}async handleRetrieverEnd(n,t,s,i){logger.debug(`handleRetrieverEnd runId - ${t}, parentRunId ${s}`),this.endTracing({runId:t,output:{documents:n},tags:i});}async handleRetrieverError(n,t,s,i){logger.debug(`handleRetrieverError runId - ${t}, parentRunId ${s}`),this.endTracing({runId:t,error:n,tags:i});}async flushAsync(){return this.client.flush()}};export{b as OpikCallbackHandler};
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "opik-langchain",
|
|
3
3
|
"description": "Opik TypeScript and JavaScript SDK integration with LangChain",
|
|
4
|
-
"version": "1.0.
|
|
4
|
+
"version": "1.0.2",
|
|
5
5
|
"engines": {
|
|
6
6
|
"node": ">=18"
|
|
7
7
|
},
|
|
@@ -32,20 +32,18 @@
|
|
|
32
32
|
"typescript-sdk",
|
|
33
33
|
"comet"
|
|
34
34
|
],
|
|
35
|
-
"main": "./dist/index.cjs",
|
|
36
|
-
"module": "./dist/index.js",
|
|
37
|
-
"types": "./dist/index.d.ts",
|
|
38
|
-
"type": "module",
|
|
39
35
|
"exports": {
|
|
40
|
-
"
|
|
36
|
+
"./package.json": "./package.json",
|
|
37
|
+
".": {
|
|
41
38
|
"types": "./dist/index.d.ts",
|
|
42
|
-
"
|
|
43
|
-
|
|
44
|
-
"import": {
|
|
45
|
-
"types": "./dist/index.d.mts",
|
|
46
|
-
"default": "./dist/index.mjs"
|
|
39
|
+
"import": "./dist/index.js",
|
|
40
|
+
"require": "./dist/index.cjs"
|
|
47
41
|
}
|
|
48
42
|
},
|
|
43
|
+
"main": "dist/index.cjs",
|
|
44
|
+
"module": "dist/index.js",
|
|
45
|
+
"types": "dist/index.d.ts",
|
|
46
|
+
"type": "module",
|
|
49
47
|
"scripts": {
|
|
50
48
|
"build": "tsup",
|
|
51
49
|
"watch": "tsup --watch",
|
|
@@ -58,11 +56,9 @@
|
|
|
58
56
|
"dist/**/*",
|
|
59
57
|
"README.md"
|
|
60
58
|
],
|
|
61
|
-
"dependencies": {
|
|
62
|
-
"opik": "^1.6.12"
|
|
63
|
-
},
|
|
64
59
|
"peerDependencies": {
|
|
65
|
-
"@langchain/core": "^0.3.42"
|
|
60
|
+
"@langchain/core": "^0.3.42",
|
|
61
|
+
"opik": "^1.6.12"
|
|
66
62
|
},
|
|
67
63
|
"devDependencies": {
|
|
68
64
|
"typescript": "^5.7.2",
|