@librechat/agents 3.0.1 → 3.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/dist/cjs/common/enum.cjs +0 -1
- package/dist/cjs/common/enum.cjs.map +1 -1
- package/dist/cjs/llm/providers.cjs +0 -2
- package/dist/cjs/llm/providers.cjs.map +1 -1
- package/dist/cjs/main.cjs +2 -0
- package/dist/cjs/main.cjs.map +1 -1
- package/dist/cjs/tools/Calculator.cjs +45 -0
- package/dist/cjs/tools/Calculator.cjs.map +1 -0
- package/dist/esm/common/enum.mjs +0 -1
- package/dist/esm/common/enum.mjs.map +1 -1
- package/dist/esm/llm/providers.mjs +0 -2
- package/dist/esm/llm/providers.mjs.map +1 -1
- package/dist/esm/main.mjs +1 -0
- package/dist/esm/main.mjs.map +1 -1
- package/dist/esm/tools/Calculator.mjs +24 -0
- package/dist/esm/tools/Calculator.mjs.map +1 -0
- package/dist/types/common/enum.d.ts +0 -1
- package/dist/types/index.d.ts +1 -0
- package/dist/types/tools/Calculator.d.ts +8 -0
- package/dist/types/types/llm.d.ts +1 -6
- package/package.json +6 -4
- package/src/common/enum.ts +0 -1
- package/src/index.ts +1 -0
- package/src/llm/providers.ts +0 -2
- package/src/scripts/abort.ts +34 -15
- package/src/scripts/cli.ts +25 -20
- package/src/scripts/cli2.ts +23 -15
- package/src/scripts/cli3.ts +35 -29
- package/src/scripts/cli4.ts +1 -2
- package/src/scripts/cli5.ts +1 -2
- package/src/scripts/code_exec.ts +1 -2
- package/src/scripts/code_exec_simple.ts +1 -2
- package/src/scripts/content.ts +33 -15
- package/src/scripts/simple.ts +1 -2
- package/src/scripts/stream.ts +33 -15
- package/src/scripts/test-tools-before-handoff.ts +17 -28
- package/src/scripts/tools.ts +4 -6
- package/src/specs/anthropic.simple.test.ts +1 -1
- package/src/specs/azure.simple.test.ts +1 -1
- package/src/specs/openai.simple.test.ts +1 -1
- package/src/specs/openrouter.simple.test.ts +1 -1
- package/src/tools/Calculator.test.ts +278 -0
- package/src/tools/Calculator.ts +25 -0
- package/src/types/llm.ts +0 -6
- package/dist/types/tools/example.d.ts +0 -78
- package/src/proto/CollabGraph.ts +0 -269
- package/src/proto/TaskManager.ts +0 -243
- package/src/proto/collab.ts +0 -200
- package/src/proto/collab_design.ts +0 -184
- package/src/proto/collab_design_v2.ts +0 -224
- package/src/proto/collab_design_v3.ts +0 -255
- package/src/proto/collab_design_v4.ts +0 -220
- package/src/proto/collab_design_v5.ts +0 -251
- package/src/proto/collab_graph.ts +0 -181
- package/src/proto/collab_original.ts +0 -123
- package/src/proto/example.ts +0 -93
- package/src/proto/example_new.ts +0 -68
- package/src/proto/example_old.ts +0 -201
- package/src/proto/example_test.ts +0 -152
- package/src/proto/example_test_anthropic.ts +0 -100
- package/src/proto/log_stream.ts +0 -202
- package/src/proto/main_collab_community_event.ts +0 -133
- package/src/proto/main_collab_design_v2.ts +0 -96
- package/src/proto/main_collab_design_v4.ts +0 -100
- package/src/proto/main_collab_design_v5.ts +0 -135
- package/src/proto/main_collab_global_analysis.ts +0 -122
- package/src/proto/main_collab_hackathon_event.ts +0 -153
- package/src/proto/main_collab_space_mission.ts +0 -153
- package/src/proto/main_philosophy.ts +0 -210
- package/src/proto/original_script.ts +0 -126
- package/src/proto/standard.ts +0 -100
- package/src/proto/stream.ts +0 -56
- package/src/proto/tasks.ts +0 -118
- package/src/proto/tools/global_analysis_tools.ts +0 -86
- package/src/proto/tools/space_mission_tools.ts +0 -60
- package/src/proto/vertexai.ts +0 -54
- package/src/tools/example.ts +0 -129
package/src/proto/example_new.ts
DELETED
|
@@ -1,68 +0,0 @@
|
|
|
1
|
-
import dotenv from 'dotenv';
|
|
2
|
-
import { ToolNode } from '@langchain/langgraph/prebuilt';
|
|
3
|
-
import { TavilySearchResults } from '@langchain/community/tools/tavily_search';
|
|
4
|
-
import { ChatAnthropic } from '@langchain/anthropic';
|
|
5
|
-
import { AIMessage, BaseMessage } from '@langchain/core/messages';
|
|
6
|
-
import { SqliteSaver } from '@langchain/langgraph/checkpoint/sqlite';
|
|
7
|
-
import { START, END, MessageGraph } from '@langchain/langgraph';
|
|
8
|
-
dotenv.config();
|
|
9
|
-
|
|
10
|
-
// Define the function that determines whether to continue or not
|
|
11
|
-
/* @ts-ignore */
|
|
12
|
-
function shouldContinue(messages) {
|
|
13
|
-
const lastMessage = messages[messages.length - 1];
|
|
14
|
-
// If there is no function call, then we finish
|
|
15
|
-
if (!(lastMessage instanceof AIMessage && lastMessage.tool_calls)) {
|
|
16
|
-
return END;
|
|
17
|
-
} else {
|
|
18
|
-
return 'action';
|
|
19
|
-
}
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
// Define tools and model
|
|
23
|
-
const tools = [new TavilySearchResults({ maxResults: 1 })];
|
|
24
|
-
const model = new ChatAnthropic({ model: 'claude-3-haiku-20240307' }).bindTools(tools);
|
|
25
|
-
|
|
26
|
-
// Define the workflow
|
|
27
|
-
const workflow = new MessageGraph()
|
|
28
|
-
.addNode('agent', model)
|
|
29
|
-
/* @ts-ignore */
|
|
30
|
-
.addNode('action', new ToolNode(tools));
|
|
31
|
-
|
|
32
|
-
workflow.addEdge(START, 'agent');
|
|
33
|
-
workflow.addConditionalEdges('agent', shouldContinue);
|
|
34
|
-
workflow.addEdge('action', 'agent');
|
|
35
|
-
|
|
36
|
-
// Set up memory
|
|
37
|
-
const memory = SqliteSaver.fromConnString(':memory:');
|
|
38
|
-
|
|
39
|
-
// Compile the app
|
|
40
|
-
const app = workflow.compile({ checkpointer: memory, interruptBefore: ['action'] });
|
|
41
|
-
|
|
42
|
-
// Run the graph
|
|
43
|
-
async function runGraph() {
|
|
44
|
-
const thread = { configurable: { thread_id: '4' } };
|
|
45
|
-
|
|
46
|
-
console.log('Initial run:');
|
|
47
|
-
for await (const event of await app.stream(
|
|
48
|
-
[['user', 'what is the weather in sf currently']],
|
|
49
|
-
{ ...thread, streamMode: 'values' }
|
|
50
|
-
)) {
|
|
51
|
-
for (const v of event.values()) {
|
|
52
|
-
console.log(v);
|
|
53
|
-
}
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
console.log('\nResuming after interruption:');
|
|
57
|
-
for await (const event of await app.stream(null, {
|
|
58
|
-
...thread,
|
|
59
|
-
streamMode: 'values',
|
|
60
|
-
})) {
|
|
61
|
-
for (const v of event.values()) {
|
|
62
|
-
console.log(v);
|
|
63
|
-
}
|
|
64
|
-
}
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
// Execute the graph
|
|
68
|
-
runGraph().catch(console.error);
|
package/src/proto/example_old.ts
DELETED
|
@@ -1,201 +0,0 @@
|
|
|
1
|
-
import fs from 'fs/promises';
|
|
2
|
-
import { pull } from 'langchain/hub';
|
|
3
|
-
import { ChatAnthropic } from '@langchain/anthropic';
|
|
4
|
-
import type { ChatPromptTemplate } from '@langchain/core/prompts';
|
|
5
|
-
import { AgentExecutor, createToolCallingAgent, AgentStep } from 'langchain/agents';
|
|
6
|
-
import { TavilySearchResults } from '@langchain/community/tools/tavily_search';
|
|
7
|
-
import type { RunLogPatch } from '@langchain/core/tracers/log_stream';
|
|
8
|
-
import dotenv from 'dotenv';
|
|
9
|
-
|
|
10
|
-
type ExtractedJSONPatchOperation = Pick<RunLogPatch, 'ops'>;
|
|
11
|
-
type OperationType = ExtractedJSONPatchOperation extends { ops: (infer T)[] } ? T : never;
|
|
12
|
-
|
|
13
|
-
// Load environment variables from .env file
|
|
14
|
-
dotenv.config();
|
|
15
|
-
|
|
16
|
-
// Define the tools the agent will have access to.
|
|
17
|
-
const tools = [new TavilySearchResults({})];
|
|
18
|
-
|
|
19
|
-
const llm = new ChatAnthropic({
|
|
20
|
-
model: 'claude-3-haiku-20240307',
|
|
21
|
-
streaming: true,
|
|
22
|
-
});
|
|
23
|
-
|
|
24
|
-
// Get the prompt to use - you can modify this!
|
|
25
|
-
// If you want to see the prompt in full, you can at:
|
|
26
|
-
// https://smith.langchain.com/hub/hwchase17/openai-functions-agent
|
|
27
|
-
const prompt = await pull<ChatPromptTemplate>(
|
|
28
|
-
'hwchase17/openai-functions-agent'
|
|
29
|
-
);
|
|
30
|
-
|
|
31
|
-
const agent = await createToolCallingAgent({
|
|
32
|
-
llm,
|
|
33
|
-
tools,
|
|
34
|
-
prompt,
|
|
35
|
-
});
|
|
36
|
-
|
|
37
|
-
const agentExecutor = new AgentExecutor({
|
|
38
|
-
agent,
|
|
39
|
-
tools,
|
|
40
|
-
});
|
|
41
|
-
|
|
42
|
-
const logStream = await agentExecutor.streamLog({
|
|
43
|
-
input: 'what are the current US election polls 2024. today is 7/6/24',
|
|
44
|
-
});
|
|
45
|
-
|
|
46
|
-
const finalState: RunLogPatch[] = [];
|
|
47
|
-
const outputs: RunLogPatch[] = [];
|
|
48
|
-
let accumulatedOutput = '';
|
|
49
|
-
let accumulatedArguments = '';
|
|
50
|
-
|
|
51
|
-
let functionName: string | undefined = undefined;
|
|
52
|
-
|
|
53
|
-
function processStreamedOutput(op: any) {
|
|
54
|
-
let output = '';
|
|
55
|
-
if (op.value.text !== undefined) {
|
|
56
|
-
output += op.value.text;
|
|
57
|
-
}
|
|
58
|
-
if (op.value.message && op.value.message.kwargs) {
|
|
59
|
-
const kwargs = op.value.message.kwargs;
|
|
60
|
-
if (kwargs.content) {
|
|
61
|
-
output += kwargs.content;
|
|
62
|
-
}
|
|
63
|
-
}
|
|
64
|
-
if (output) {
|
|
65
|
-
accumulatedOutput += output;
|
|
66
|
-
process.stdout.write(output);
|
|
67
|
-
}
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
// A helper function to handle the event pattern for logged arguments
|
|
71
|
-
function handleLoggedArgument(loggedArgument: any) {
|
|
72
|
-
if (loggedArgument.value?.message?.additional_kwargs?.function_call) {
|
|
73
|
-
const functionCall = loggedArgument.value.message.additional_kwargs.function_call;
|
|
74
|
-
|
|
75
|
-
if (functionCall.name) {
|
|
76
|
-
functionName = functionCall.name;
|
|
77
|
-
process.stdout.write(`Logged Function Name:
|
|
78
|
-
${JSON.stringify(functionCall, null, 2)}
|
|
79
|
-
`);
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
if (functionCall.arguments) {
|
|
83
|
-
accumulatedArguments += functionCall.arguments;
|
|
84
|
-
// Print the part of the argument as it comes
|
|
85
|
-
// process.stdout.write(`Logged Argument: { "arguments": "${functionCall.arguments}" }\n`);
|
|
86
|
-
process.stdout.write(`Logged Argument:\n${JSON.stringify(functionCall, null, 2)}`);
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
// Check if the full arguments string has been accumulated
|
|
90
|
-
if (accumulatedArguments.startsWith('{') && accumulatedArguments.endsWith('}')) {
|
|
91
|
-
// Build the final logged argument string
|
|
92
|
-
const completeArguments = accumulatedArguments;
|
|
93
|
-
const namePart = functionName ? `"name": "${functionName}", ` : '';
|
|
94
|
-
|
|
95
|
-
console.log(`\nLogged Argument: {\n ${namePart}"arguments": ${completeArguments}\n}\n`);
|
|
96
|
-
|
|
97
|
-
// Reset accumulators
|
|
98
|
-
accumulatedArguments = '';
|
|
99
|
-
functionName = undefined;
|
|
100
|
-
}
|
|
101
|
-
}
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
for await (const chunk of logStream) {
|
|
105
|
-
finalState.push(chunk);
|
|
106
|
-
outputs.push(chunk);
|
|
107
|
-
|
|
108
|
-
if (!chunk.ops) continue;
|
|
109
|
-
|
|
110
|
-
for (const op of chunk.ops) {
|
|
111
|
-
if (isStreamedOutput(op)) {
|
|
112
|
-
processStreamedOutput(op);
|
|
113
|
-
if (hasFunctionCall(op)) {
|
|
114
|
-
handleLoggedArgument(op);
|
|
115
|
-
}
|
|
116
|
-
} else if (isFinalOutput(op)) {
|
|
117
|
-
printFinalOutput(op);
|
|
118
|
-
}
|
|
119
|
-
}
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
function isStreamedOutput(op: OperationType) {
|
|
123
|
-
return op.op === 'add' && (
|
|
124
|
-
op.path.includes('/streamed_output/-') ||
|
|
125
|
-
op.path.includes('/streamed_output_str/-')
|
|
126
|
-
);
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
function hasFunctionCall(op: OperationType) {
|
|
130
|
-
return (op as any)?.['value']?.message?.additional_kwargs?.function_call;
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
function isFinalOutput(op: OperationType) {
|
|
134
|
-
return op.op === 'add' &&
|
|
135
|
-
op.value?.output &&
|
|
136
|
-
op.path?.startsWith('/logs/') &&
|
|
137
|
-
op.path?.endsWith('final_output') &&
|
|
138
|
-
!op.path?.includes('Runnable');
|
|
139
|
-
}
|
|
140
|
-
|
|
141
|
-
function printFinalOutput(op: OperationType) {
|
|
142
|
-
process.stdout.write(JSON.stringify(op, null, 2));
|
|
143
|
-
process.stdout.write(`
|
|
144
|
-
|
|
145
|
-
########################_START_##########################
|
|
146
|
-
${JSON.stringify((op as any)?.['value']?.output, null, 2)}
|
|
147
|
-
########################__END__##########################
|
|
148
|
-
|
|
149
|
-
`);
|
|
150
|
-
}
|
|
151
|
-
|
|
152
|
-
// Define types for the final output structure
|
|
153
|
-
interface FinalOutput {
|
|
154
|
-
id: string;
|
|
155
|
-
streamed_output: Array<{
|
|
156
|
-
intermediateSteps?: AgentStep[];
|
|
157
|
-
output?: string;
|
|
158
|
-
}>;
|
|
159
|
-
final_output?: {
|
|
160
|
-
output: string;
|
|
161
|
-
};
|
|
162
|
-
logs: Record<string, any>;
|
|
163
|
-
}
|
|
164
|
-
|
|
165
|
-
// Process finalState to create FinalOutput
|
|
166
|
-
const finalOutput: FinalOutput = {
|
|
167
|
-
id: '',
|
|
168
|
-
streamed_output: [],
|
|
169
|
-
logs: {},
|
|
170
|
-
};
|
|
171
|
-
|
|
172
|
-
for (const patch of finalState) {
|
|
173
|
-
if (patch.ops) {
|
|
174
|
-
for (const op of patch.ops) {
|
|
175
|
-
if (op.op === 'add' || op.op === 'replace') {
|
|
176
|
-
if (op.path === '/id') {
|
|
177
|
-
finalOutput.id = op.value;
|
|
178
|
-
} else if (op.path === '/streamed_output/-') {
|
|
179
|
-
finalOutput.streamed_output.push(op.value);
|
|
180
|
-
} else if (op.path === '/final_output') {
|
|
181
|
-
finalOutput.final_output = op.value;
|
|
182
|
-
} else if (op.path.startsWith('/logs/')) {
|
|
183
|
-
const logKey = op.path.split('/')[2];
|
|
184
|
-
finalOutput.logs[logKey] = op.value;
|
|
185
|
-
}
|
|
186
|
-
}
|
|
187
|
-
}
|
|
188
|
-
}
|
|
189
|
-
}
|
|
190
|
-
|
|
191
|
-
// Save outputs to a JSON file
|
|
192
|
-
await fs.writeFile('outputs.json', JSON.stringify(outputs, null, 2));
|
|
193
|
-
console.log('\n\nOutputs have been saved to outputs.json');
|
|
194
|
-
|
|
195
|
-
// Save the final state separately
|
|
196
|
-
await fs.writeFile('final_output.json', JSON.stringify(finalOutput, null, 2));
|
|
197
|
-
console.log('\n\nFinal output has been saved to final_output.json');
|
|
198
|
-
|
|
199
|
-
// Save the cleaned-up accumulated output
|
|
200
|
-
await fs.writeFile('cleaned_output.txt', accumulatedOutput);
|
|
201
|
-
console.log('\n\nCleaned output has been saved to cleaned_output.txt');
|
|
@@ -1,152 +0,0 @@
|
|
|
1
|
-
import { BaseMessage, HumanMessage } from "@langchain/core/messages";
|
|
2
|
-
import { ChatAnthropic } from "@langchain/anthropic";
|
|
3
|
-
import { ChatPromptTemplate } from "@langchain/core/prompts";
|
|
4
|
-
import { TavilySearchResults } from '@langchain/community/tools/tavily_search';
|
|
5
|
-
import { RunnableConfig } from "@langchain/core/runnables";
|
|
6
|
-
import {
|
|
7
|
-
END,
|
|
8
|
-
// MemorySaver,
|
|
9
|
-
START,
|
|
10
|
-
StateGraph,
|
|
11
|
-
StateGraphArgs,
|
|
12
|
-
} from "@langchain/langgraph";
|
|
13
|
-
|
|
14
|
-
interface IState {
|
|
15
|
-
messages: BaseMessage[];
|
|
16
|
-
userInfo: string;
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
async function main() {
|
|
20
|
-
|
|
21
|
-
const graphState: StateGraphArgs<IState>["channels"] = {
|
|
22
|
-
messages: {
|
|
23
|
-
value: (x: BaseMessage[], y: BaseMessage[]) => x.concat(y),
|
|
24
|
-
default: () => [],
|
|
25
|
-
},
|
|
26
|
-
userInfo: {
|
|
27
|
-
value: (x?: string, y?: string) => {
|
|
28
|
-
return y ? y : x ? x : "N/A";
|
|
29
|
-
},
|
|
30
|
-
default: () => "N/A",
|
|
31
|
-
},
|
|
32
|
-
};
|
|
33
|
-
|
|
34
|
-
const promptTemplate = ChatPromptTemplate.fromMessages([
|
|
35
|
-
["system", "You are a helpful assistant.\n\n## User Info:\n{userInfo}"],
|
|
36
|
-
["placeholder", "{messages}"],
|
|
37
|
-
]);
|
|
38
|
-
|
|
39
|
-
const initializeModel = (bindTools = false) => {
|
|
40
|
-
const model = new ChatAnthropic({
|
|
41
|
-
// model: "claude-3-haiku-20240307",
|
|
42
|
-
model: 'claude-3-5-sonnet-20240620'
|
|
43
|
-
})
|
|
44
|
-
if (bindTools) {
|
|
45
|
-
return model.bindTools([new TavilySearchResults()]);
|
|
46
|
-
}
|
|
47
|
-
return model;
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
const callModel = async (
|
|
51
|
-
state: { messages: BaseMessage[]; userInfo: string },
|
|
52
|
-
config?: RunnableConfig,
|
|
53
|
-
) => {
|
|
54
|
-
const { messages, userInfo } = state;
|
|
55
|
-
|
|
56
|
-
/*
|
|
57
|
-
|
|
58
|
-
This correctly streams tokens when
|
|
59
|
-
we don't bind tools, but if we do, it fails.
|
|
60
|
-
|
|
61
|
-
*/
|
|
62
|
-
const model = initializeModel(true);
|
|
63
|
-
// const model = initializeModel();
|
|
64
|
-
const chain = promptTemplate.pipe(model);
|
|
65
|
-
const response = await chain.invoke(
|
|
66
|
-
{
|
|
67
|
-
messages,
|
|
68
|
-
userInfo,
|
|
69
|
-
},
|
|
70
|
-
config,
|
|
71
|
-
);
|
|
72
|
-
return { messages: [response] };
|
|
73
|
-
};
|
|
74
|
-
|
|
75
|
-
const fetchUserInformation = async (
|
|
76
|
-
_: { messages: BaseMessage[] },
|
|
77
|
-
config?: RunnableConfig,
|
|
78
|
-
) => {
|
|
79
|
-
const userDB = {
|
|
80
|
-
user1: {
|
|
81
|
-
name: "John Doe",
|
|
82
|
-
email: "jod@langchain.ai",
|
|
83
|
-
phone: "+1234567890",
|
|
84
|
-
},
|
|
85
|
-
user2: {
|
|
86
|
-
name: "Jane Doe",
|
|
87
|
-
email: "jad@langchain.ai",
|
|
88
|
-
phone: "+0987654321",
|
|
89
|
-
},
|
|
90
|
-
};
|
|
91
|
-
const userId = config?.configurable?.user;
|
|
92
|
-
if (userId) {
|
|
93
|
-
const user = userDB[userId as keyof typeof userDB];
|
|
94
|
-
if (user) {
|
|
95
|
-
return {
|
|
96
|
-
userInfo:
|
|
97
|
-
`Name: ${user.name}\nEmail: ${user.email}\nPhone: ${user.phone}`,
|
|
98
|
-
};
|
|
99
|
-
}
|
|
100
|
-
}
|
|
101
|
-
return { userInfo: "N/A" };
|
|
102
|
-
};
|
|
103
|
-
|
|
104
|
-
const workflow = new StateGraph({
|
|
105
|
-
channels: graphState,
|
|
106
|
-
})
|
|
107
|
-
.addNode("fetchUserInfo", fetchUserInformation)
|
|
108
|
-
.addNode("agent", callModel)
|
|
109
|
-
.addEdge(START, "fetchUserInfo")
|
|
110
|
-
.addEdge("fetchUserInfo", "agent")
|
|
111
|
-
.addEdge("agent", END);
|
|
112
|
-
|
|
113
|
-
// Here we only save in-memory
|
|
114
|
-
// let memory = new MemorySaver();
|
|
115
|
-
// const graph = workflow.compile({ checkpointer: memory });
|
|
116
|
-
const graph = workflow.compile();
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
const config = {
|
|
120
|
-
configurable: {
|
|
121
|
-
user: "user1",
|
|
122
|
-
},
|
|
123
|
-
};
|
|
124
|
-
const inputs = {
|
|
125
|
-
messages: [new HumanMessage("Could you remind me of my email?")],
|
|
126
|
-
};
|
|
127
|
-
|
|
128
|
-
const stream = graph.streamEvents(inputs, {
|
|
129
|
-
...config,
|
|
130
|
-
version: "v2",
|
|
131
|
-
streamMode: "values",
|
|
132
|
-
});
|
|
133
|
-
for await (const { event, data } of stream) {
|
|
134
|
-
|
|
135
|
-
if (event === "on_chat_model_start") {
|
|
136
|
-
console.log('=======CHAT_MODEL_START=======');
|
|
137
|
-
console.dir(data, { depth: null });
|
|
138
|
-
} else if (event === "on_chat_model_stream") {
|
|
139
|
-
console.dir(data, { depth: null });
|
|
140
|
-
} else if (event === "on_chat_model_end") {
|
|
141
|
-
console.log('=======CHAT_MODEL_END=======');
|
|
142
|
-
console.dir(data, { depth: null });
|
|
143
|
-
} else {
|
|
144
|
-
console.log(event);
|
|
145
|
-
}
|
|
146
|
-
}
|
|
147
|
-
}
|
|
148
|
-
|
|
149
|
-
main().catch((err) => {
|
|
150
|
-
console.error(err);
|
|
151
|
-
process.exit(1);
|
|
152
|
-
});
|
|
@@ -1,100 +0,0 @@
|
|
|
1
|
-
import { BaseMessage, HumanMessage, AIMessageChunk, AIMessage } from "@langchain/core/messages";
|
|
2
|
-
import { ChatAnthropic } from "@langchain/anthropic";
|
|
3
|
-
import { ChatPromptTemplate } from "@langchain/core/prompts";
|
|
4
|
-
import { TavilySearchResults } from '@langchain/community/tools/tavily_search';
|
|
5
|
-
import { RunnableConfig } from "@langchain/core/runnables";
|
|
6
|
-
import { ToolNode } from '@langchain/langgraph/prebuilt';
|
|
7
|
-
import {
|
|
8
|
-
END,
|
|
9
|
-
START,
|
|
10
|
-
StateGraph,
|
|
11
|
-
StateGraphArgs,
|
|
12
|
-
} from "@langchain/langgraph";
|
|
13
|
-
|
|
14
|
-
interface IState {
|
|
15
|
-
messages: BaseMessage[];
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
async function main() {
|
|
19
|
-
const graphState: StateGraphArgs<IState>["channels"] = {
|
|
20
|
-
messages: {
|
|
21
|
-
value: (x: BaseMessage[], y: BaseMessage[]) => x.concat(y),
|
|
22
|
-
default: () => [],
|
|
23
|
-
},
|
|
24
|
-
};
|
|
25
|
-
|
|
26
|
-
const promptTemplate = ChatPromptTemplate.fromMessages([
|
|
27
|
-
["system", "You are a helpful assistant."],
|
|
28
|
-
["placeholder", "{messages}"],
|
|
29
|
-
]);
|
|
30
|
-
|
|
31
|
-
const initializeModel = (bindTools = false) => {
|
|
32
|
-
const model = new ChatAnthropic({
|
|
33
|
-
model: 'claude-3-5-sonnet-20240620'
|
|
34
|
-
})
|
|
35
|
-
if (bindTools) {
|
|
36
|
-
return model.bindTools([new TavilySearchResults()]);
|
|
37
|
-
}
|
|
38
|
-
return model;
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
const callModel = async (
|
|
42
|
-
state: { messages: BaseMessage[] },
|
|
43
|
-
config?: RunnableConfig,
|
|
44
|
-
) => {
|
|
45
|
-
const { messages } = state;
|
|
46
|
-
|
|
47
|
-
const model = initializeModel(true);
|
|
48
|
-
const chain = promptTemplate.pipe(model);
|
|
49
|
-
const response = await chain.invoke(
|
|
50
|
-
{
|
|
51
|
-
messages,
|
|
52
|
-
},
|
|
53
|
-
config,
|
|
54
|
-
);
|
|
55
|
-
return { messages: [response] };
|
|
56
|
-
};
|
|
57
|
-
|
|
58
|
-
const tools = [new TavilySearchResults()];
|
|
59
|
-
const toolNode = new ToolNode<IState>(tools);
|
|
60
|
-
|
|
61
|
-
const routeMessage = (state: IState): string => {
|
|
62
|
-
const lastMessage = state.messages[state.messages.length - 1] as AIMessage;
|
|
63
|
-
if (!lastMessage?.tool_calls?.length) {
|
|
64
|
-
return END;
|
|
65
|
-
}
|
|
66
|
-
return "tools";
|
|
67
|
-
};
|
|
68
|
-
|
|
69
|
-
const workflow = new StateGraph({
|
|
70
|
-
channels: graphState,
|
|
71
|
-
})
|
|
72
|
-
.addNode("agent", callModel)
|
|
73
|
-
.addNode("tools", toolNode)
|
|
74
|
-
.addEdge(START, "agent")
|
|
75
|
-
.addConditionalEdges("agent", routeMessage)
|
|
76
|
-
.addEdge("tools", "agent");
|
|
77
|
-
|
|
78
|
-
const graph = workflow.compile();
|
|
79
|
-
|
|
80
|
-
const inputs = {
|
|
81
|
-
messages: [new HumanMessage("Could you search the internet for information about LangChain?")],
|
|
82
|
-
};
|
|
83
|
-
|
|
84
|
-
const stream = graph.streamEvents(inputs, {
|
|
85
|
-
version: "v2",
|
|
86
|
-
streamMode: "values",
|
|
87
|
-
});
|
|
88
|
-
|
|
89
|
-
for await (const { event, data } of stream) {
|
|
90
|
-
console.log(event)
|
|
91
|
-
if (event === "on_chat_model_stream") {
|
|
92
|
-
console.log(data);
|
|
93
|
-
}
|
|
94
|
-
}
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
main().catch((err) => {
|
|
98
|
-
console.error(err);
|
|
99
|
-
process.exit(1);
|
|
100
|
-
});
|