add history tool
This commit is contained in:
@@ -3,6 +3,7 @@ import { ChatPromptTemplate, MessagesPlaceholder } from '@langchain/core/prompts
|
|||||||
import { createReactAgent } from '@langchain/langgraph/prebuilt';
|
import { createReactAgent } from '@langchain/langgraph/prebuilt';
|
||||||
import { MemorySaver } from '@langchain/langgraph';
|
import { MemorySaver } from '@langchain/langgraph';
|
||||||
import gigachat from './gigachat';
|
import gigachat from './gigachat';
|
||||||
|
import { SupportContextTool } from './support-context-tool';
|
||||||
|
|
||||||
export interface SupportAgentConfig {
|
export interface SupportAgentConfig {
|
||||||
temperature?: number;
|
temperature?: number;
|
||||||
@@ -22,30 +23,31 @@ export class SupportAgent {
|
|||||||
private systemPrompt: string;
|
private systemPrompt: string;
|
||||||
private threadId: string;
|
private threadId: string;
|
||||||
private isFirstMessage: boolean;
|
private isFirstMessage: boolean;
|
||||||
|
private userId: string;
|
||||||
|
|
||||||
constructor(config: SupportAgentConfig = {}) {
|
constructor(config: SupportAgentConfig = {}) {
|
||||||
this.systemPrompt = this.getDefaultSystemPrompt();
|
this.systemPrompt = this.getDefaultSystemPrompt();
|
||||||
this.threadId = config.threadId || 'default';
|
this.threadId = config.threadId || 'default';
|
||||||
|
this.userId = this.threadId;
|
||||||
this.memorySaver = new MemorySaver();
|
this.memorySaver = new MemorySaver();
|
||||||
this.isFirstMessage = true;
|
this.isFirstMessage = true;
|
||||||
|
|
||||||
// Настраиваем модель с заданной температурой
|
|
||||||
this.llm = gigachat;
|
this.llm = gigachat;
|
||||||
if (config.temperature !== undefined) {
|
if (config.temperature !== undefined) {
|
||||||
this.llm.temperature = config.temperature;
|
this.llm.temperature = config.temperature;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Создаем агента без инструментов для простого чата
|
const tools = [
|
||||||
|
new SupportContextTool(this.userId)
|
||||||
|
];
|
||||||
|
|
||||||
this.agent = createReactAgent({
|
this.agent = createReactAgent({
|
||||||
llm: this.llm,
|
llm: this.llm,
|
||||||
tools: [],
|
tools: tools,
|
||||||
checkpointSaver: this.memorySaver
|
checkpointSaver: this.memorySaver
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Получить системный промпт по умолчанию для агента поддержки
|
|
||||||
*/
|
|
||||||
private getDefaultSystemPrompt(): string {
|
private getDefaultSystemPrompt(): string {
|
||||||
return `Ты - профессиональный агент службы поддержки.
|
return `Ты - профессиональный агент службы поддержки.
|
||||||
|
|
||||||
@@ -56,29 +58,26 @@ export class SupportAgent {
|
|||||||
- Проявлять эмпатию к проблемам пользователей
|
- Проявлять эмпатию к проблемам пользователей
|
||||||
- Если не знаешь ответ, честно сообщить об этом и предложить альтернативные способы получения помощи
|
- Если не знаешь ответ, честно сообщить об этом и предложить альтернативные способы получения помощи
|
||||||
|
|
||||||
|
ВАЖНО: У тебя есть доступ к инструменту get_support_context, который позволяет получить историю предыдущих сообщений пользователя.
|
||||||
|
ВСЕГДА используй этот инструмент ПЕРВЫМ ДЕЛОМ при получении каждого нового сообщения, чтобы понять контекст и предыдущие обращения пользователя.
|
||||||
|
Только после получения контекста отвечай на вопрос пользователя.
|
||||||
|
|
||||||
|
Если в истории есть предыдущие обращения, обязательно ссылайся на них в своем ответе, показывая что помнишь предыдущее общение.
|
||||||
|
|
||||||
Всегда отвечай на русском языке и старайся быть максимально полезным.`;
|
Всегда отвечай на русском языке и старайся быть максимально полезным.`;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Обработать сообщение пользователя и получить ответ
|
|
||||||
*/
|
|
||||||
public async processMessage(userMessage: string): Promise<SupportResponse> {
|
public async processMessage(userMessage: string): Promise<SupportResponse> {
|
||||||
try {
|
try {
|
||||||
// Создаем массив сообщений
|
|
||||||
const messages: BaseMessage[] = [];
|
const messages: BaseMessage[] = [];
|
||||||
|
|
||||||
// Добавляем системный промпт только в первом сообщении
|
|
||||||
if (this.isFirstMessage) {
|
if (this.isFirstMessage) {
|
||||||
messages.push(new SystemMessage(this.systemPrompt));
|
messages.push(new SystemMessage(this.systemPrompt));
|
||||||
this.isFirstMessage = false;
|
this.isFirstMessage = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Добавляем сообщение пользователя
|
|
||||||
messages.push(new HumanMessage(userMessage));
|
messages.push(new HumanMessage(userMessage));
|
||||||
|
|
||||||
// Получаем ответ от агента
|
|
||||||
const response = await this.agent.invoke({
|
const response = await this.agent.invoke({
|
||||||
messages: messages
|
messages: messages
|
||||||
}, {
|
}, {
|
||||||
@@ -87,7 +86,6 @@ export class SupportAgent {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// Извлекаем последнее сообщение от ассистента
|
|
||||||
const lastMessage = response.messages[response.messages.length - 1];
|
const lastMessage = response.messages[response.messages.length - 1];
|
||||||
|
|
||||||
return {
|
return {
|
||||||
@@ -105,19 +103,19 @@ export class SupportAgent {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Очистить историю диалога
|
|
||||||
*/
|
|
||||||
public async clearHistory(): Promise<void> {
|
public async clearHistory(): Promise<void> {
|
||||||
this.memorySaver = new MemorySaver();
|
this.memorySaver = new MemorySaver();
|
||||||
|
|
||||||
|
const tools = [
|
||||||
|
new SupportContextTool(this.userId)
|
||||||
|
];
|
||||||
|
|
||||||
this.agent = createReactAgent({
|
this.agent = createReactAgent({
|
||||||
llm: this.llm,
|
llm: this.llm,
|
||||||
tools: [],
|
tools: tools,
|
||||||
checkpointSaver: this.memorySaver
|
checkpointSaver: this.memorySaver
|
||||||
});
|
});
|
||||||
// Сбрасываем флаг первого сообщения
|
|
||||||
this.isFirstMessage = true;
|
this.isFirstMessage = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,56 @@
|
|||||||
|
import { StructuredTool, ToolRunnableConfig } from '@langchain/core/tools';
|
||||||
|
import { z } from 'zod';
|
||||||
|
import { CallbackManagerForToolRun } from '@langchain/core/callbacks/manager';
|
||||||
|
import { getSupabaseClient } from '../supabaseClient';
|
||||||
|
|
||||||
|
export class SupportContextTool extends StructuredTool {
|
||||||
|
name = 'get_support_context';
|
||||||
|
description = 'Получает последние 10 сообщений из истории поддержки для понимания контекста разговора. Используй этот инструмент в начале разговора.';
|
||||||
|
|
||||||
|
schema = z.object({});
|
||||||
|
|
||||||
|
private userId: string;
|
||||||
|
|
||||||
|
constructor(userId: string) {
|
||||||
|
super();
|
||||||
|
this.userId = userId;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected async _call(
|
||||||
|
arg: z.infer<typeof this.schema>,
|
||||||
|
runManager?: CallbackManagerForToolRun,
|
||||||
|
parentConfig?: ToolRunnableConfig<Record<string, any>>
|
||||||
|
): Promise<string> {
|
||||||
|
try {
|
||||||
|
const supabase = getSupabaseClient();
|
||||||
|
|
||||||
|
const { data: messages, error } = await supabase
|
||||||
|
.from('support')
|
||||||
|
.select('message, is_from_user, created_at')
|
||||||
|
.eq('user_id', this.userId)
|
||||||
|
.order('created_at', { ascending: false })
|
||||||
|
.limit(10);
|
||||||
|
|
||||||
|
if (error) {
|
||||||
|
return 'Не удалось получить историю сообщений.';
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!messages || messages.length === 0) {
|
||||||
|
return 'История сообщений поддержки пуста. Это первое обращение пользователя.';
|
||||||
|
}
|
||||||
|
|
||||||
|
const chronologicalMessages = messages.reverse();
|
||||||
|
|
||||||
|
const contextMessages = chronologicalMessages.map((msg, index) => {
|
||||||
|
const role = msg.is_from_user ? 'Пользователь' : 'Агент поддержки';
|
||||||
|
const time = new Date(msg.created_at).toLocaleString('ru-RU');
|
||||||
|
return `${index + 1}. [${time}] ${role}: ${msg.message}`;
|
||||||
|
}).join('\n');
|
||||||
|
|
||||||
|
return `Последние сообщения из истории поддержки (${messages.length} сообщений):\n\n${contextMessages}\n\nИспользуй этот контекст для понимания предыдущих обращений пользователя и предоставления более точных ответов.`;
|
||||||
|
|
||||||
|
} catch (error) {
|
||||||
|
return 'Произошла ошибка при получении истории сообщений.';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user