Added simple pipeline
This commit is contained in:
1 parent
daa5645d5f
commit
4194d4239f
6 files changed
+556
-31
No files matched your search
+160
@@ -0,0 +1,160 @@
|
||||
import { HumanMessage, SystemMessage } from '@langchain/core/messages';
|
||||
import { Runnable } from '@langchain/core/runnables';
|
||||
import { DynamicStructuredTool } from '@langchain/core/tools';
|
||||
import { ChatOpenAI } from '@langchain/openai';
|
||||
import Handlebars from 'handlebars';
|
||||
import { z } from 'zod';
|
||||
|
||||
interface PipelineStep {
|
||||
name: string;
|
||||
prompt: string;
|
||||
}
|
||||
|
||||
interface Pipeline {
|
||||
description: string;
|
||||
systemPrompt: string;
|
||||
steps: PipelineStep[];
|
||||
}
|
||||
|
||||
class MockMcpToolsService {
|
||||
async getTools(): Promise<DynamicStructuredTool[]> {
|
||||
const echoTool = new DynamicStructuredTool({
|
||||
name: 'echo',
|
||||
description: 'Возвращает введенную строку.',
|
||||
schema: z.object({ input: z.string().describe('Строка для эхо.') }),
|
||||
func: async (input: { input: string }) => {
|
||||
return input.input;
|
||||
},
|
||||
});
|
||||
|
||||
const getCurrentDateTool = new DynamicStructuredTool({
|
||||
name: 'get_current_date',
|
||||
description: 'Возвращает текущую дату в формате ISO.',
|
||||
schema: z.object({}),
|
||||
func: async () => {
|
||||
return new Date().toISOString();
|
||||
},
|
||||
});
|
||||
|
||||
return [echoTool, getCurrentDateTool];
|
||||
}
|
||||
}
|
||||
|
||||
class PipelineExecutor {
|
||||
private readonly mcpToolsService: MockMcpToolsService;
|
||||
|
||||
constructor() {
|
||||
this.mcpToolsService = new MockMcpToolsService();
|
||||
}
|
||||
|
||||
private async initChain(openAIApiKey: string): Promise<Runnable> {
|
||||
const tools = await this.mcpToolsService.getTools();
|
||||
const llm = new ChatOpenAI({
|
||||
model: 'gpt-4o',
|
||||
temperature: 0.2,
|
||||
openAIApiKey: openAIApiKey,
|
||||
});
|
||||
return llm.bindTools(tools);
|
||||
}
|
||||
|
||||
private buildMessages(
|
||||
systemPrompts: string[],
|
||||
variables: Record<string, string> = {},
|
||||
): (HumanMessage | SystemMessage)[] {
|
||||
return [
|
||||
...systemPrompts.map((prompt) =>
|
||||
Object.keys(variables).length
|
||||
? new SystemMessage(Handlebars.compile(prompt)(variables))
|
||||
: new SystemMessage(prompt),
|
||||
),
|
||||
new SystemMessage(`Текущая дата и время: ${new Date().toISOString()}`),
|
||||
];
|
||||
}
|
||||
|
||||
private renderPrompt(
|
||||
prompt: string,
|
||||
variables: Record<string, string> = {},
|
||||
): string {
|
||||
return Object.keys(variables).length
|
||||
? Handlebars.compile(prompt)(variables)
|
||||
: prompt;
|
||||
}
|
||||
|
||||
async executeChain(params: {
|
||||
pipeline: Pipeline;
|
||||
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 chain = await this.initChain(params.openAIApiKey);
|
||||
const messages = this.buildMessages(
|
||||
[params.pipeline.systemPrompt, ...systemPrompts],
|
||||
variables,
|
||||
);
|
||||
const results: string[] = [];
|
||||
|
||||
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 ?? '');
|
||||
}
|
||||
return results;
|
||||
}
|
||||
}
|
||||
|
||||
async function main() {
|
||||
require('dotenv').config();
|
||||
const openAIApiKey = process.env.OPENAI_API_KEY;
|
||||
|
||||
if (!openAIApiKey) {
|
||||
console.error(
|
||||
'Ошибка: Переменная окружения OPENAI_API_KEY не установлена.',
|
||||
);
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
const pipelineExecutor = new PipelineExecutor();
|
||||
|
||||
const testPipeline: Pipeline = {
|
||||
description: 'Тестовый пайплайн',
|
||||
systemPrompt:
|
||||
'Ты полезный ассистент, который всегда отвечает на русском языке.',
|
||||
steps: [
|
||||
{
|
||||
name: 'Приветствие',
|
||||
prompt: 'Скажи привет, используя имя {{username}}.',
|
||||
},
|
||||
{
|
||||
name: 'Использование инструмента',
|
||||
prompt:
|
||||
'Используй инструмент `echo` чтобы сказать "Не потоковая обработка работает!"',
|
||||
},
|
||||
{
|
||||
name: 'Получение даты',
|
||||
prompt: 'Какая сейчас дата? Используй инструмент `get_current_date`.',
|
||||
},
|
||||
{ name: 'Завершение', prompt: 'Подтверди, что все шаги выполнены.' },
|
||||
],
|
||||
};
|
||||
|
||||
const variables = {
|
||||
username: 'Пользователь',
|
||||
};
|
||||
|
||||
const systemPrompts = ['Отвечай кратко и по существу.'];
|
||||
|
||||
const results = await pipelineExecutor.executeChain({
|
||||
pipeline: testPipeline,
|
||||
variables: variables,
|
||||
systemPrompts: systemPrompts,
|
||||
openAIApiKey: openAIApiKey,
|
||||
});
|
||||
console.log('Результаты выполнения пайплайна:', results);
|
||||
}
|
||||
|
||||
main().catch(console.error);
|
||||
Reference in new issue
Block a user