116 lines
3.6 KiB
JavaScript
116 lines
3.6 KiB
JavaScript
import 'dotenv/config';
|
|
import { createDeepAgent } from "deepagents";
|
|
import { ChatOpenAI } from "@langchain/openai";
|
|
import { AIMessageChunk, ToolMessage } from "langchain";
|
|
import { SystemMessage, HumanMessage, AIMessage } from "@langchain/core/messages";
|
|
import { ChatDeepSeek } from "@langchain/deepseek";
|
|
import Prompts from "./prompts.js";
|
|
|
|
export default class EscortAgent {
|
|
constructor() {
|
|
}
|
|
|
|
clearMessages() {
|
|
this.messages = [];
|
|
}
|
|
|
|
// msg: { ts: "2023-08-01 10:00:00", content: "你好" }
|
|
async streamChat(userInfo, msgs, callback) {
|
|
if (!msgs.length) {
|
|
return;
|
|
}
|
|
|
|
const agent = this._genAgent(userInfo);
|
|
msgs.forEach(msg => {
|
|
if (msg.type === "clear") {
|
|
this.messages = [];
|
|
} else {
|
|
this.messages.push(new HumanMessage(msg.content));
|
|
}
|
|
});
|
|
|
|
if (this.messages.length === 0) {
|
|
return;
|
|
}
|
|
|
|
const INTERESTING_NODES = new Set(["model_request", "tools"]);
|
|
for await (const [namespace, mode, data] of await agent.stream(
|
|
{ messages: this.messages },
|
|
{
|
|
recursion_limit: 50,
|
|
streamMode: ["updates", "messages", "custom"], subgraphs: true,
|
|
configurable: {
|
|
thread_id: 'default-session'
|
|
}
|
|
})) {
|
|
const isSubagent = namespace.some(s => s.startsWith("tools:"));
|
|
const source = isSubagent ? "subagent" : "main";
|
|
if (mode === "updates") {
|
|
for (const nodeName of Object.keys(data)) {
|
|
if (!INTERESTING_NODES.has(nodeName)) continue;
|
|
// Main agent updates (empty namespace)
|
|
if (namespace.length === 0) {
|
|
for (const [nodeName, data_] of Object.entries(data)) {
|
|
if (nodeName === "tools") {
|
|
// Subagent results returned to main agent
|
|
for (const msg of data_.messages ?? []) {
|
|
if (msg.type === "tool") {
|
|
console.log(`\nSubagent complete: ${msg.name}`);
|
|
console.log(` Result: ${String(msg.content).slice(0, 200)}...`);
|
|
}
|
|
}
|
|
} else if (nodeName === "model_request") {
|
|
this.messages.push(...data_.messages);
|
|
}
|
|
}
|
|
} else {
|
|
// Subagent updates (non-empty namespace)
|
|
for (const [nodeName, data_] of Object.entries(data)) {
|
|
console.log(` [${namespace[0]}] step: ${nodeName}`);
|
|
}
|
|
}
|
|
}
|
|
} else if (mode === "messages") {
|
|
const [message] = data;
|
|
if (message.tool_call_chunks?.length) {
|
|
continue;
|
|
}
|
|
if (AIMessageChunk.isInstance(message)) {
|
|
if (message.text && !message.tool_call_chunks?.length) {
|
|
callback(source, "ai", message.text, message.id);
|
|
}
|
|
if (message.additional_kwargs.reasoning_content && !message.tool_call_chunks?.length) {
|
|
callback(source, "reasoning", message.additional_kwargs.reasoning_content, message.id);
|
|
}
|
|
}
|
|
if (ToolMessage.isInstance(message) && message.text) {
|
|
callback(source, "tool", message.text, message.id);
|
|
}
|
|
} else if (mode === "custom") {
|
|
this.logger.info("custom: ", data);
|
|
}
|
|
}
|
|
}
|
|
|
|
_genAgent(userInfo) {
|
|
if (this.agent) {
|
|
return this.agent;
|
|
}
|
|
|
|
this.messages = [];
|
|
|
|
this.model = new ChatDeepSeek({
|
|
model: 'deepseek-v4-flash',
|
|
apiKey: 'sk-a58ccd82b7ba4ce3ac176a88c9381095',
|
|
temperature: 0.3
|
|
});
|
|
|
|
this.agent = createDeepAgent({
|
|
name: "deep-agent",
|
|
model: this.model,
|
|
systemPrompt: Prompts.buildSystemPrompt(userInfo)
|
|
});
|
|
|
|
return this.agent;
|
|
}
|
|
} |