feat: Implement tool calls and error handling in pipeline execution
This commit is contained in:
1 parent
4194d4239f
commit
6047368080
1 file changed
+59
-12
+59
-12
@@ -1,4 +1,8 @@
|
||||
import { HumanMessage, SystemMessage } from '@langchain/core/messages';
|
||||
import {
|
||||
HumanMessage,
|
||||
SystemMessage,
|
||||
ToolMessage,
|
||||
} from '@langchain/core/messages';
|
||||
import { Runnable } from '@langchain/core/runnables';
|
||||
import { DynamicStructuredTool } from '@langchain/core/tools';
|
||||
import { ChatOpenAI } from '@langchain/openai';
|
||||
@@ -23,6 +27,7 @@ class MockMcpToolsService {
|
||||
description: 'Возвращает введенную строку.',
|
||||
schema: z.object({ input: z.string().describe('Строка для эхо.') }),
|
||||
func: async (input: { input: string }) => {
|
||||
console.log(`Вызов инструмента 'echo' с входом: ${input.input}`);
|
||||
return input.input;
|
||||
},
|
||||
});
|
||||
@@ -32,6 +37,7 @@ class MockMcpToolsService {
|
||||
description: 'Возвращает текущую дату в формате ISO.',
|
||||
schema: z.object({}),
|
||||
func: async () => {
|
||||
console.log('Вызов инструмента "get_current_date"');
|
||||
return new Date().toISOString();
|
||||
},
|
||||
});
|
||||
@@ -82,15 +88,14 @@ class PipelineExecutor {
|
||||
|
||||
async executeChain(params: {
|
||||
pipeline: Pipeline;
|
||||
variables: Record<string, string>;
|
||||
systemPrompts: string[];
|
||||
variables?: Record<string, string>;
|
||||
systemPrompts?: string[];
|
||||
openAIApiKey: string;
|
||||
}): Promise<string[]> {
|
||||
const variables = params.variables === undefined ? {} : params.variables;
|
||||
const systemPrompts =
|
||||
params.systemPrompts === undefined ? [] : params.systemPrompts;
|
||||
const variables = params.variables ?? {};
|
||||
const systemPrompts = params.systemPrompts ?? [];
|
||||
const chain = await this.initChain(params.openAIApiKey);
|
||||
const messages = this.buildMessages(
|
||||
const initialMessages = this.buildMessages(
|
||||
[params.pipeline.systemPrompt, ...systemPrompts],
|
||||
variables,
|
||||
);
|
||||
@@ -98,10 +103,48 @@ class PipelineExecutor {
|
||||
|
||||
for (const { prompt } of params.pipeline.steps) {
|
||||
const renderedPrompt = this.renderPrompt(prompt, variables);
|
||||
console.log({ renderedPrompt });
|
||||
const stepMessages = [...messages, new HumanMessage(renderedPrompt)];
|
||||
const response = await chain.invoke(stepMessages);
|
||||
results.push(response?.content ?? '');
|
||||
const currentMessages = [
|
||||
...initialMessages,
|
||||
new HumanMessage(renderedPrompt),
|
||||
];
|
||||
let response = await chain.invoke(currentMessages);
|
||||
|
||||
while (response.tool_calls && response.tool_calls.length > 0) {
|
||||
const toolCalls = response.tool_calls;
|
||||
currentMessages.push(response);
|
||||
|
||||
for (const toolCall of toolCalls) {
|
||||
try {
|
||||
const tools = await this.mcpToolsService.getTools();
|
||||
const tool = tools.find((t) => t.name === toolCall.name);
|
||||
|
||||
if (!tool) {
|
||||
throw new Error(`Tool ${toolCall.name} not found`);
|
||||
}
|
||||
|
||||
const toolResult = await tool.func(toolCall.args);
|
||||
currentMessages.push(
|
||||
new ToolMessage({
|
||||
tool_call_id: toolCall.id,
|
||||
content: JSON.stringify(toolResult),
|
||||
}),
|
||||
);
|
||||
} catch (error) {
|
||||
console.error(
|
||||
`Ошибка выполнения инструмента ${toolCall.name}:`,
|
||||
error,
|
||||
);
|
||||
currentMessages.push(
|
||||
new ToolMessage({
|
||||
tool_call_id: toolCall.id,
|
||||
content: `Error: ${error.message}`,
|
||||
}),
|
||||
);
|
||||
}
|
||||
}
|
||||
response = await chain.invoke(currentMessages);
|
||||
}
|
||||
results.push(response?.content ?? '<empty>');
|
||||
}
|
||||
return results;
|
||||
}
|
||||
@@ -138,7 +181,7 @@ async function main() {
|
||||
name: 'Получение даты',
|
||||
prompt: 'Какая сейчас дата? Используй инструмент `get_current_date`.',
|
||||
},
|
||||
{ name: 'Завершение', prompt: 'Подтверди, что все шаги выполнены.' },
|
||||
{ name: 'Завершение', prompt: 'Напиши резюме, что ты сделал' },
|
||||
],
|
||||
};
|
||||
|
||||
@@ -148,6 +191,7 @@ async function main() {
|
||||
|
||||
const systemPrompts = ['Отвечай кратко и по существу.'];
|
||||
|
||||
try {
|
||||
const results = await pipelineExecutor.executeChain({
|
||||
pipeline: testPipeline,
|
||||
variables: variables,
|
||||
@@ -155,6 +199,9 @@ async function main() {
|
||||
openAIApiKey: openAIApiKey,
|
||||
});
|
||||
console.log('Результаты выполнения пайплайна:', results);
|
||||
} catch (error) {
|
||||
console.error('Ошибка при выполнении пайплайна:', error);
|
||||
}
|
||||
}
|
||||
|
||||
main().catch(console.error);
|
||||
Reference in new issue
Block a user