@traccia2/sdk 0.0.1 → 0.0.3
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 +235 -1
- package/dist/integrations/auto-langchain.d.ts +108 -0
- package/dist/integrations/auto-langchain.d.ts.map +1 -0
- package/dist/integrations/auto-langchain.js +276 -0
- package/dist/integrations/auto-langchain.js.map +1 -0
- package/dist/integrations/auto-langgraph.d.ts +104 -0
- package/dist/integrations/auto-langgraph.d.ts.map +1 -0
- package/dist/integrations/auto-langgraph.js +240 -0
- package/dist/integrations/auto-langgraph.js.map +1 -0
- package/dist/integrations/index.d.ts +3 -0
- package/dist/integrations/index.d.ts.map +1 -1
- package/dist/integrations/index.js +26 -1
- package/dist/integrations/index.js.map +1 -1
- package/dist/integrations/ollama-integration.d.ts +122 -0
- package/dist/integrations/ollama-integration.d.ts.map +1 -0
- package/dist/integrations/ollama-integration.js +330 -0
- package/dist/integrations/ollama-integration.js.map +1 -0
- package/dist/tracer/span.d.ts +3 -1
- package/dist/tracer/span.d.ts.map +1 -1
- package/dist/tracer/span.js +6 -1
- package/dist/tracer/span.js.map +1 -1
- package/dist/tracer/tracer.js +1 -1
- package/dist/tracer/tracer.js.map +1 -1
- package/package.json +6 -1
- package/src/integrations/auto-langchain.ts +283 -0
- package/src/integrations/auto-langgraph.ts +248 -0
- package/src/integrations/index.ts +30 -0
- package/src/integrations/ollama-integration.ts +358 -0
- package/src/tracer/span.ts +10 -1
- package/src/tracer/tracer.ts +1 -1
|
@@ -0,0 +1,283 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Automatic LangChain instrumentation - simple one-line setup.
|
|
3
|
+
*
|
|
4
|
+
* Instead of manually passing callbacks to every component, use these
|
|
5
|
+
* convenience functions for automatic instrumentation with zero boilerplate.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import { TraciaCallbackHandler } from './langchain-callback';
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Global handler instance to avoid creating multiple handlers
|
|
12
|
+
*/
|
|
13
|
+
let globalTraciaHandler: TraciaCallbackHandler | null = null;
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Get or create the global Traccia callback handler.
|
|
17
|
+
*
|
|
18
|
+
* @example
|
|
19
|
+
* // Instead of:
|
|
20
|
+
* const handler = new TraciaCallbackHandler();
|
|
21
|
+
* const model = new ChatOpenAI({ callbacks: [handler] });
|
|
22
|
+
*
|
|
23
|
+
* // Just do:
|
|
24
|
+
* const model = new ChatOpenAI({ callbacks: [getTraciaHandler()] });
|
|
25
|
+
*/
|
|
26
|
+
export function getTraciaHandler(): TraciaCallbackHandler {
|
|
27
|
+
if (!globalTraciaHandler) {
|
|
28
|
+
globalTraciaHandler = new TraciaCallbackHandler();
|
|
29
|
+
}
|
|
30
|
+
return globalTraciaHandler;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Wrap any LangChain model/chain/agent with automatic tracing.
|
|
35
|
+
*
|
|
36
|
+
* @example
|
|
37
|
+
* const model = new ChatOpenAI({ modelName: 'gpt-4' });
|
|
38
|
+
* const tracedModel = withTracing(model);
|
|
39
|
+
*
|
|
40
|
+
* const response = await tracedModel.invoke({ input: 'Hello' });
|
|
41
|
+
* // Automatically traced!
|
|
42
|
+
*/
|
|
43
|
+
export function withTracing<T extends any>(component: T): T {
|
|
44
|
+
const handler = getTraciaHandler();
|
|
45
|
+
|
|
46
|
+
// For models and chains, add the handler to callbacks
|
|
47
|
+
if (component && typeof component === 'object') {
|
|
48
|
+
if ('callbacks' in component) {
|
|
49
|
+
// If callbacks exist, add our handler
|
|
50
|
+
const existing = (component as any).callbacks || [];
|
|
51
|
+
(component as any).callbacks = Array.isArray(existing)
|
|
52
|
+
? [...existing, handler]
|
|
53
|
+
: [existing, handler];
|
|
54
|
+
} else {
|
|
55
|
+
// Otherwise create callbacks array
|
|
56
|
+
(component as any).callbacks = [handler];
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
return component;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* Create a traced ChatOpenAI model with one line.
|
|
65
|
+
*
|
|
66
|
+
* @example
|
|
67
|
+
* const model = createTracedOpenAI({ modelName: 'gpt-4' });
|
|
68
|
+
* const response = await model.invoke({ input: 'Hello' });
|
|
69
|
+
*/
|
|
70
|
+
export async function createTracedOpenAI(config: any): Promise<any> {
|
|
71
|
+
try {
|
|
72
|
+
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
|
73
|
+
const langchainOpenai = require('@langchain/openai');
|
|
74
|
+
const model = new langchainOpenai.ChatOpenAI(config);
|
|
75
|
+
return withTracing(model);
|
|
76
|
+
} catch (error) {
|
|
77
|
+
throw new Error(
|
|
78
|
+
'Failed to create traced ChatOpenAI. Make sure @langchain/openai is installed.'
|
|
79
|
+
);
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* Create a traced agent executor with one line.
|
|
85
|
+
*
|
|
86
|
+
* @example
|
|
87
|
+
* const executor = createTracedAgentExecutor({
|
|
88
|
+
* agent,
|
|
89
|
+
* tools,
|
|
90
|
+
* agentExecutorOptions: { maxIterations: 10 }
|
|
91
|
+
* });
|
|
92
|
+
*
|
|
93
|
+
* const result = await executor.invoke({ input: 'What time is it?' });
|
|
94
|
+
*/
|
|
95
|
+
export async function createTracedAgentExecutor(options: {
|
|
96
|
+
agent: any;
|
|
97
|
+
tools: any[];
|
|
98
|
+
agentExecutorOptions?: Record<string, any>;
|
|
99
|
+
}): Promise<any> {
|
|
100
|
+
try {
|
|
101
|
+
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
|
102
|
+
const langchainAgents = require('langchain/agents');
|
|
103
|
+
const { agent, tools, agentExecutorOptions = {} } = options;
|
|
104
|
+
|
|
105
|
+
const executor = langchainAgents.AgentExecutor.fromAgentAndTools({
|
|
106
|
+
agent,
|
|
107
|
+
tools,
|
|
108
|
+
...agentExecutorOptions,
|
|
109
|
+
callbacks: [getTraciaHandler(), ...(agentExecutorOptions.callbacks || [])],
|
|
110
|
+
});
|
|
111
|
+
|
|
112
|
+
return executor;
|
|
113
|
+
} catch (error) {
|
|
114
|
+
throw new Error(
|
|
115
|
+
'Failed to create traced AgentExecutor. Make sure langchain/agents is installed.'
|
|
116
|
+
);
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
/**
|
|
121
|
+
* Create a traced LLMChain with one line.
|
|
122
|
+
*
|
|
123
|
+
* @example
|
|
124
|
+
* const chain = createTracedLLMChain({
|
|
125
|
+
* llm: new ChatOpenAI(),
|
|
126
|
+
* prompt: chatPrompt
|
|
127
|
+
* });
|
|
128
|
+
*
|
|
129
|
+
* const result = await chain.invoke({ question: 'Hello?' });
|
|
130
|
+
*/
|
|
131
|
+
export async function createTracedLLMChain(options: {
|
|
132
|
+
llm: any;
|
|
133
|
+
prompt: any;
|
|
134
|
+
}): Promise<any> {
|
|
135
|
+
try {
|
|
136
|
+
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
|
137
|
+
const langchainChains = require('langchain/chains');
|
|
138
|
+
const { llm, prompt } = options;
|
|
139
|
+
|
|
140
|
+
const chain = new langchainChains.LLMChain({
|
|
141
|
+
llm: withTracing(llm),
|
|
142
|
+
prompt,
|
|
143
|
+
callbacks: [getTraciaHandler()],
|
|
144
|
+
});
|
|
145
|
+
|
|
146
|
+
return chain;
|
|
147
|
+
} catch (error) {
|
|
148
|
+
throw new Error(
|
|
149
|
+
'Failed to create traced LLMChain. Make sure langchain/chains is installed.'
|
|
150
|
+
);
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
/**
|
|
155
|
+
* Decorator for methods that should be traced.
|
|
156
|
+
*
|
|
157
|
+
* @example
|
|
158
|
+
* class MyAgent {
|
|
159
|
+
* @traced('agent-process')
|
|
160
|
+
* async process(input: string) {
|
|
161
|
+
* return await this.llm.invoke({ input });
|
|
162
|
+
* }
|
|
163
|
+
* }
|
|
164
|
+
*
|
|
165
|
+
* const agent = new MyAgent();
|
|
166
|
+
* const result = await agent.process('Hello'); // Automatically traced!
|
|
167
|
+
*/
|
|
168
|
+
export function traced(spanName: string) {
|
|
169
|
+
return function (
|
|
170
|
+
_target: any,
|
|
171
|
+
propertyKey: string,
|
|
172
|
+
descriptor: PropertyDescriptor
|
|
173
|
+
) {
|
|
174
|
+
const originalMethod = descriptor.value;
|
|
175
|
+
|
|
176
|
+
descriptor.value = async function (...args: any[]) {
|
|
177
|
+
const { getTracer } = await import('../auto');
|
|
178
|
+
const tracer = getTracer('decorated-method');
|
|
179
|
+
|
|
180
|
+
return tracer.startActiveSpan(spanName, async (span) => {
|
|
181
|
+
try {
|
|
182
|
+
span.setAttribute('method', propertyKey);
|
|
183
|
+
span.setAttribute('args_count', args.length);
|
|
184
|
+
const result = await originalMethod.apply(this, args);
|
|
185
|
+
span.setAttribute('success', true);
|
|
186
|
+
return result;
|
|
187
|
+
} catch (error) {
|
|
188
|
+
if (error instanceof Error) {
|
|
189
|
+
span.recordException(error);
|
|
190
|
+
}
|
|
191
|
+
throw error;
|
|
192
|
+
}
|
|
193
|
+
});
|
|
194
|
+
};
|
|
195
|
+
|
|
196
|
+
return descriptor;
|
|
197
|
+
};
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
/**
|
|
201
|
+
* Simple configuration helper for common LangChain setup patterns.
|
|
202
|
+
*
|
|
203
|
+
* @example
|
|
204
|
+
* const { model, executor } = await setupLangChainWithTracing({
|
|
205
|
+
* modelName: 'gpt-4',
|
|
206
|
+
* tools: [weatherTool, calculatorTool],
|
|
207
|
+
* systemPrompt: 'You are a helpful assistant.'
|
|
208
|
+
* });
|
|
209
|
+
*
|
|
210
|
+
* const result = await executor.invoke({ input: 'What is the weather?' });
|
|
211
|
+
*/
|
|
212
|
+
export async function setupLangChainWithTracing(options: {
|
|
213
|
+
modelName?: string;
|
|
214
|
+
modelConfig?: Record<string, any>;
|
|
215
|
+
tools?: any[];
|
|
216
|
+
systemPrompt?: string;
|
|
217
|
+
}): Promise<{
|
|
218
|
+
model: any;
|
|
219
|
+
executor: any;
|
|
220
|
+
handler: TraciaCallbackHandler;
|
|
221
|
+
}> {
|
|
222
|
+
try {
|
|
223
|
+
const {
|
|
224
|
+
modelName = 'gpt-4',
|
|
225
|
+
modelConfig = {},
|
|
226
|
+
tools = [],
|
|
227
|
+
systemPrompt,
|
|
228
|
+
} = options;
|
|
229
|
+
|
|
230
|
+
// Create traced model
|
|
231
|
+
const model = await createTracedOpenAI({
|
|
232
|
+
modelName,
|
|
233
|
+
...modelConfig,
|
|
234
|
+
});
|
|
235
|
+
|
|
236
|
+
// Create agent if tools provided
|
|
237
|
+
let executor = null;
|
|
238
|
+
if (tools.length > 0) {
|
|
239
|
+
try {
|
|
240
|
+
// Try to create agent with tools
|
|
241
|
+
const langchainAgents = require('langchain/agents');
|
|
242
|
+
const langchainCore = require('@langchain/core/prompts');
|
|
243
|
+
|
|
244
|
+
// Create prompt
|
|
245
|
+
const prompt = langchainCore.ChatPromptTemplate.fromMessages([
|
|
246
|
+
...(systemPrompt
|
|
247
|
+
? [['system', systemPrompt]]
|
|
248
|
+
: [['system', 'You are a helpful assistant.']]),
|
|
249
|
+
['human', '{input}'],
|
|
250
|
+
new langchainCore.MessagesPlaceholder('agent_scratchpad'),
|
|
251
|
+
]);
|
|
252
|
+
|
|
253
|
+
// Create agent
|
|
254
|
+
const agent = await langchainAgents.createOpenAIToolsAgent({
|
|
255
|
+
llmWithTools: model,
|
|
256
|
+
tools,
|
|
257
|
+
prompt,
|
|
258
|
+
callbacks: [getTraciaHandler()],
|
|
259
|
+
});
|
|
260
|
+
|
|
261
|
+
// Create executor
|
|
262
|
+
executor = await createTracedAgentExecutor({
|
|
263
|
+
agent,
|
|
264
|
+
tools,
|
|
265
|
+
});
|
|
266
|
+
} catch (error) {
|
|
267
|
+
// If agent creation fails, just return model without executor
|
|
268
|
+
console.warn('Could not create agent executor:', (error as Error).message);
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
return {
|
|
273
|
+
model,
|
|
274
|
+
executor,
|
|
275
|
+
handler: getTraciaHandler(),
|
|
276
|
+
};
|
|
277
|
+
} catch (error) {
|
|
278
|
+
const err = error as Error;
|
|
279
|
+
throw new Error(
|
|
280
|
+
`Failed to setup LangChain with tracing: ${err.message}`
|
|
281
|
+
);
|
|
282
|
+
}
|
|
283
|
+
}
|
|
@@ -0,0 +1,248 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Automatic LangGraph instrumentation - simple one-line setup.
|
|
3
|
+
*
|
|
4
|
+
* Wrap your LangGraph nodes and conditionals to get tracing without
|
|
5
|
+
* any boilerplate code.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import {
|
|
9
|
+
instrumentLangGraph,
|
|
10
|
+
createTracedNode,
|
|
11
|
+
createTracedConditional,
|
|
12
|
+
} from './langgraph-instrumentation';
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Wrap a StateGraph with automatic tracing.
|
|
16
|
+
*
|
|
17
|
+
* @example
|
|
18
|
+
* const graph = new StateGraph(GraphState);
|
|
19
|
+
* graph.addNode('step1', processStep1);
|
|
20
|
+
* graph.addNode('step2', processStep2);
|
|
21
|
+
* graph.addEdge('step1', 'step2');
|
|
22
|
+
*
|
|
23
|
+
* // Just wrap your graph!
|
|
24
|
+
* const traced = wrapGraphWithTracing(graph);
|
|
25
|
+
* const compiled = traced.compile();
|
|
26
|
+
*
|
|
27
|
+
* const result = await compiled.invoke({ input: 'data' });
|
|
28
|
+
* // Fully traced with no other changes!
|
|
29
|
+
*/
|
|
30
|
+
export function wrapGraphWithTracing(graph: any, options: any = {}): any {
|
|
31
|
+
return instrumentLangGraph(graph, {
|
|
32
|
+
traceGraphExecution: true,
|
|
33
|
+
traceNodeExecution: true,
|
|
34
|
+
captureGraphState: options.captureState ?? false,
|
|
35
|
+
...options,
|
|
36
|
+
});
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Create a traced node function with one line.
|
|
41
|
+
*
|
|
42
|
+
* @example
|
|
43
|
+
* // Wrap your existing node:
|
|
44
|
+
* const existingNode = (state) => ({ result: 'done' });
|
|
45
|
+
* const traced = tracedNode('process-step', existingNode);
|
|
46
|
+
* graph.addNode('process', traced);
|
|
47
|
+
*/
|
|
48
|
+
export function tracedNode(
|
|
49
|
+
nodeName: string,
|
|
50
|
+
nodeFunction: (state: any) => Promise<any> | any
|
|
51
|
+
): (state: any) => Promise<any> {
|
|
52
|
+
return createTracedNode(nodeName, nodeFunction);
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* Create a traced conditional edge router with one line.
|
|
57
|
+
*
|
|
58
|
+
* @example
|
|
59
|
+
* // Wrap your existing router:
|
|
60
|
+
* const decideRoute = (state) => state.approved ? 'done' : 'review';
|
|
61
|
+
* const traced = tracedConditional('route-check', decideRoute);
|
|
62
|
+
* graph.addConditionalEdges('check', traced);
|
|
63
|
+
*/
|
|
64
|
+
export function tracedConditional(
|
|
65
|
+
conditionalName: string,
|
|
66
|
+
routeFunction: (state: Record<string, any>) => string
|
|
67
|
+
): (state: Record<string, any>) => string {
|
|
68
|
+
return createTracedConditional(conditionalName, routeFunction);
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* Factory function to create a traced agent graph from simple config.
|
|
73
|
+
*
|
|
74
|
+
* @example
|
|
75
|
+
* const graph = createSimpleTracedGraph({
|
|
76
|
+
* nodes: {
|
|
77
|
+
* 'process': async (state) => ({ result: await process(state.input) }),
|
|
78
|
+
* 'review': async (state) => ({ reviewed: true }),
|
|
79
|
+
* },
|
|
80
|
+
* edges: [
|
|
81
|
+
* { from: '__start__', to: 'process' },
|
|
82
|
+
* { from: 'process', to: 'review' },
|
|
83
|
+
* { from: 'review', to: '__end__' },
|
|
84
|
+
* ],
|
|
85
|
+
* });
|
|
86
|
+
*
|
|
87
|
+
* const result = await graph.compile().invoke({ input: 'data' });
|
|
88
|
+
*/
|
|
89
|
+
export async function createSimpleTracedGraph(options: {
|
|
90
|
+
nodes: Record<string, (state: any) => Promise<any>>;
|
|
91
|
+
edges: Array<{ from: string; to: string }>;
|
|
92
|
+
conditionals?: Record<
|
|
93
|
+
string,
|
|
94
|
+
{ router: (state: any) => string; routes: string[] }
|
|
95
|
+
>;
|
|
96
|
+
startState?: Record<string, any>;
|
|
97
|
+
}): Promise<any> {
|
|
98
|
+
try {
|
|
99
|
+
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
|
100
|
+
const langgraphModule = require('@langchain/langgraph');
|
|
101
|
+
const { nodes, edges, conditionals = {}, startState = {} } = options;
|
|
102
|
+
|
|
103
|
+
// Create state graph
|
|
104
|
+
const graph = new langgraphModule.StateGraph({
|
|
105
|
+
channels: startState,
|
|
106
|
+
});
|
|
107
|
+
|
|
108
|
+
// Add traced nodes
|
|
109
|
+
for (const [nodeName, nodeFunc] of Object.entries(nodes)) {
|
|
110
|
+
const tracedNodeFunc = tracedNode(nodeName, nodeFunc);
|
|
111
|
+
graph.addNode(nodeName, tracedNodeFunc);
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
// Add edges
|
|
115
|
+
for (const edge of edges) {
|
|
116
|
+
if (edge.from === '__start__') {
|
|
117
|
+
graph.setEntryPoint(edge.to);
|
|
118
|
+
} else if (edge.to === '__end__') {
|
|
119
|
+
graph.setFinishPoint(edge.from);
|
|
120
|
+
} else {
|
|
121
|
+
graph.addEdge(edge.from, edge.to);
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
// Add conditional edges
|
|
126
|
+
for (const [condName, condConfig] of Object.entries(conditionals)) {
|
|
127
|
+
const tracedRouter = tracedConditional(condName, condConfig.router);
|
|
128
|
+
graph.addConditionalEdges(condName, tracedRouter, condConfig.routes);
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
// Wrap entire graph with tracing
|
|
132
|
+
return wrapGraphWithTracing(graph);
|
|
133
|
+
} catch (error) {
|
|
134
|
+
const err = error as Error;
|
|
135
|
+
throw new Error(
|
|
136
|
+
`Failed to create simple traced graph: ${err.message}. Make sure @langchain/langgraph is installed.`
|
|
137
|
+
);
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
/**
|
|
142
|
+
* Trace a single agent function or tool with minimal setup.
|
|
143
|
+
*
|
|
144
|
+
* @example
|
|
145
|
+
* const tool = traceableFunction('my-tool', async (input) => {
|
|
146
|
+
* return processInput(input);
|
|
147
|
+
* });
|
|
148
|
+
*
|
|
149
|
+
* const result = await tool('data');
|
|
150
|
+
* // Automatically traced!
|
|
151
|
+
*/
|
|
152
|
+
export function traceableFunction<T extends (...args: any[]) => any>(
|
|
153
|
+
spanName: string,
|
|
154
|
+
fn: T
|
|
155
|
+
): T {
|
|
156
|
+
return (async (...args: any[]) => {
|
|
157
|
+
const { getTracer } = await import('../auto');
|
|
158
|
+
const tracer = getTracer('traceable-function');
|
|
159
|
+
|
|
160
|
+
return tracer.startActiveSpan(spanName, async (span) => {
|
|
161
|
+
try {
|
|
162
|
+
span.setAttribute('args_count', args.length);
|
|
163
|
+
if (args[0] && typeof args[0] === 'object') {
|
|
164
|
+
span.setAttribute('input_keys', Object.keys(args[0]).join(','));
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
const result = await fn(...args);
|
|
168
|
+
|
|
169
|
+
if (result && typeof result === 'object') {
|
|
170
|
+
span.setAttribute('output_keys', Object.keys(result).join(','));
|
|
171
|
+
}
|
|
172
|
+
span.setAttribute('success', true);
|
|
173
|
+
|
|
174
|
+
return result;
|
|
175
|
+
} catch (error) {
|
|
176
|
+
if (error instanceof Error) {
|
|
177
|
+
span.recordException(error);
|
|
178
|
+
}
|
|
179
|
+
throw error;
|
|
180
|
+
}
|
|
181
|
+
});
|
|
182
|
+
}) as T;
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
/**
|
|
186
|
+
* Quick setup for a common agent pattern: input → process → route → output.
|
|
187
|
+
*
|
|
188
|
+
* @example
|
|
189
|
+
* const graph = await createAgentWorkflow({
|
|
190
|
+
* processInput: async (state) => ({ processed: await analyze(state.input) }),
|
|
191
|
+
* routeDecision: (state) => state.processed.needsReview ? 'review' : 'done',
|
|
192
|
+
* reviewStep: async (state) => ({ reviewed: true }),
|
|
193
|
+
* });
|
|
194
|
+
*
|
|
195
|
+
* const result = await graph.compile().invoke({ input: 'user input' });
|
|
196
|
+
*/
|
|
197
|
+
export async function createAgentWorkflow(options: {
|
|
198
|
+
processInput: (state: Record<string, any>) => Promise<Record<string, any>>;
|
|
199
|
+
routeDecision: (state: Record<string, any>) => string;
|
|
200
|
+
reviewStep?: (state: Record<string, any>) => Promise<Record<string, any>>;
|
|
201
|
+
finalStep?: (state: Record<string, any>) => Promise<Record<string, any>>;
|
|
202
|
+
}): Promise<any> {
|
|
203
|
+
try {
|
|
204
|
+
const {
|
|
205
|
+
processInput,
|
|
206
|
+
routeDecision,
|
|
207
|
+
reviewStep,
|
|
208
|
+
finalStep,
|
|
209
|
+
} = options;
|
|
210
|
+
|
|
211
|
+
const nodes: Record<string, (state: any) => Promise<any>> = {
|
|
212
|
+
process: processInput,
|
|
213
|
+
};
|
|
214
|
+
|
|
215
|
+
if (reviewStep) nodes.review = reviewStep;
|
|
216
|
+
if (finalStep) nodes.final = finalStep;
|
|
217
|
+
|
|
218
|
+
const edges: Array<{ from: string; to: string }> = [
|
|
219
|
+
{ from: '__start__', to: 'process' },
|
|
220
|
+
];
|
|
221
|
+
|
|
222
|
+
const conditionals: Record<string, any> = {
|
|
223
|
+
route: {
|
|
224
|
+
router: routeDecision,
|
|
225
|
+
routes: ['done', ...(reviewStep ? ['review'] : [])],
|
|
226
|
+
},
|
|
227
|
+
};
|
|
228
|
+
|
|
229
|
+
edges.push({ from: 'process', to: 'route' });
|
|
230
|
+
|
|
231
|
+
if (reviewStep) {
|
|
232
|
+
edges.push({ from: 'review', to: finalStep ? 'final' : '__end__' });
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
if (finalStep) {
|
|
236
|
+
edges.push({ from: 'final', to: '__end__' });
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
return createSimpleTracedGraph({
|
|
240
|
+
nodes,
|
|
241
|
+
edges,
|
|
242
|
+
conditionals,
|
|
243
|
+
});
|
|
244
|
+
} catch (error) {
|
|
245
|
+
const err = error as Error;
|
|
246
|
+
throw new Error(`Failed to create agent workflow: ${err.message}`);
|
|
247
|
+
}
|
|
248
|
+
}
|
|
@@ -5,9 +5,39 @@
|
|
|
5
5
|
* @module integrations
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
|
+
// LangChain integrations
|
|
8
9
|
export { TraciaCallbackHandler } from './langchain-callback';
|
|
10
|
+
export {
|
|
11
|
+
getTraciaHandler,
|
|
12
|
+
withTracing,
|
|
13
|
+
createTracedOpenAI,
|
|
14
|
+
createTracedAgentExecutor,
|
|
15
|
+
createTracedLLMChain,
|
|
16
|
+
traced,
|
|
17
|
+
setupLangChainWithTracing,
|
|
18
|
+
} from './auto-langchain';
|
|
19
|
+
|
|
20
|
+
// LangGraph integrations
|
|
9
21
|
export {
|
|
10
22
|
instrumentLangGraph,
|
|
11
23
|
createTracedNode,
|
|
12
24
|
createTracedConditional,
|
|
13
25
|
} from './langgraph-instrumentation';
|
|
26
|
+
export {
|
|
27
|
+
wrapGraphWithTracing,
|
|
28
|
+
tracedNode,
|
|
29
|
+
tracedConditional,
|
|
30
|
+
createSimpleTracedGraph,
|
|
31
|
+
traceableFunction,
|
|
32
|
+
createAgentWorkflow,
|
|
33
|
+
} from './auto-langgraph';
|
|
34
|
+
|
|
35
|
+
// Ollama integrations
|
|
36
|
+
export {
|
|
37
|
+
createOllamaWithTracing,
|
|
38
|
+
setupOllamaWithTracing,
|
|
39
|
+
createOllamaChatbot,
|
|
40
|
+
createOllamaStreamingChatbot,
|
|
41
|
+
getOllamaSetupInstructions,
|
|
42
|
+
POPULAR_OLLAMA_MODELS,
|
|
43
|
+
} from './ollama-integration';
|