166 lines
7.2 KiB
TypeScript
166 lines
7.2 KiB
TypeScript
import { HumanMessage, AIMessage, SystemMessage, BaseMessage } from '@langchain/core/messages';
|
||
import { ChatPromptTemplate, MessagesPlaceholder } from '@langchain/core/prompts';
|
||
import { createReactAgent } from '@langchain/langgraph/prebuilt';
|
||
import { MemorySaver } from '@langchain/langgraph';
|
||
import gigachat from './gigachat';
|
||
import { SupportContextTool } from './support-context-tool';
|
||
import { KnowledgeBaseTool } from './knowledge-base-tool';
|
||
import { CreateTicketTool } from './create-ticket-tool';
|
||
|
||
export interface SupportAgentConfig {
|
||
temperature?: number;
|
||
threadId?: string;
|
||
}
|
||
|
||
export interface SupportResponse {
|
||
content: string;
|
||
success: boolean;
|
||
error?: string;
|
||
}
|
||
|
||
export class SupportAgent {
|
||
private llm: any;
|
||
private memorySaver: MemorySaver;
|
||
private agent: any;
|
||
private systemPrompt: string;
|
||
private threadId: string;
|
||
private isFirstMessage: boolean;
|
||
private userId: string;
|
||
|
||
constructor(config: SupportAgentConfig = {}) {
|
||
this.systemPrompt = this.getDefaultSystemPrompt();
|
||
this.threadId = config.threadId || 'default';
|
||
this.userId = this.threadId;
|
||
this.memorySaver = new MemorySaver();
|
||
this.isFirstMessage = true;
|
||
|
||
this.llm = gigachat;
|
||
if (config.temperature !== undefined) {
|
||
this.llm.temperature = config.temperature;
|
||
}
|
||
|
||
const tools = [
|
||
new SupportContextTool(this.userId),
|
||
new KnowledgeBaseTool()
|
||
];
|
||
|
||
this.agent = createReactAgent({
|
||
llm: this.llm,
|
||
tools: tools,
|
||
checkpointSaver: this.memorySaver
|
||
});
|
||
}
|
||
|
||
private getDefaultSystemPrompt(): string {
|
||
return `Ты - профессиональный агент службы поддержки управляющей компании.
|
||
|
||
ОСНОВНЫЕ ПРИНЦИПЫ:
|
||
- Помогай только с реальными проблемами и вопросами, связанными с ЖКХ, управляющей компанией и приложением
|
||
- Будь вежливым, профессиональным и по существу
|
||
- Если вопрос неуместен, не связан с твоими обязанностями или является развлекательным - вежливо откажись и перенаправь к основным темам
|
||
|
||
ДОСТУПНЫЕ ИНСТРУМЕНТЫ:
|
||
|
||
1. get_support_context - получает историю сообщений пользователя
|
||
ВСЕГДА используй ПЕРВЫМ при каждом новом сообщении
|
||
|
||
2. search_knowledge_base - поиск в базе знаний компании
|
||
Используй ТОЛЬКО для серьезных вопросов о:
|
||
- Процессах оплаты ЖКХ и тарифах
|
||
- Подаче заявок и документообороте
|
||
- Правилах и регламентах УК
|
||
- Технических вопросах приложения
|
||
- Процедурах и инструкциях компании
|
||
|
||
3. create_ticket - создание заявки в системе
|
||
Используй ТОЛЬКО когда:
|
||
- Пользователь сообщает о реальной проблеме (поломка, неисправность, жалоба)
|
||
- Проблема требует вмешательства УК или технических служб
|
||
- ОБЯЗАТЕЛЬНО сначала покажи пользователю полный текст заявки
|
||
- Получи ЯВНОЕ согласие пользователя перед созданием
|
||
- НЕ создавай заявки для консультационных вопросов
|
||
|
||
ПРАВИЛА ИСПОЛЬЗОВАНИЯ ИНСТРУМЕНТОВ:
|
||
- НЕ используй search_knowledge_base и create_ticket для:
|
||
* Общих вопросов и болтовни
|
||
* Развлекательных запросов
|
||
* Вопросов не по теме ЖКХ/УК
|
||
* Простых консультаций, которые можно решить обычным ответом
|
||
|
||
АЛГОРИТМ РАБОТЫ:
|
||
1. Получи контекст истории сообщений
|
||
2. Определи, является ли вопрос уместным и серьезным
|
||
3. Если нужна специфическая информация - найди в базе знаний
|
||
4. Если нужно создать заявку - покажи текст и получи согласие
|
||
5. Дай полный и полезный ответ
|
||
|
||
Всегда отвечай на русском языке и фокусируйся на помощи с реальными проблемами ЖКХ.`;
|
||
}
|
||
|
||
public async processMessage(userMessage: string, apartmentId?: string): Promise<SupportResponse> {
|
||
try {
|
||
const messages: BaseMessage[] = [];
|
||
|
||
if (this.isFirstMessage) {
|
||
messages.push(new SystemMessage(this.systemPrompt));
|
||
this.isFirstMessage = false;
|
||
}
|
||
|
||
messages.push(new HumanMessage(userMessage));
|
||
|
||
// Создаем инструменты с актуальным apartmentId
|
||
const tools = [
|
||
new SupportContextTool(this.userId),
|
||
new KnowledgeBaseTool(),
|
||
new CreateTicketTool(this.userId, apartmentId || '')
|
||
];
|
||
|
||
// Пересоздаем агента с обновленными инструментами
|
||
const tempAgent = createReactAgent({
|
||
llm: this.llm,
|
||
tools: tools,
|
||
checkpointSaver: this.memorySaver
|
||
});
|
||
|
||
const response = await tempAgent.invoke({
|
||
messages: messages
|
||
}, {
|
||
configurable: {
|
||
thread_id: this.threadId
|
||
}
|
||
});
|
||
|
||
const lastMessage = response.messages[response.messages.length - 1];
|
||
|
||
return {
|
||
content: typeof lastMessage.content === 'string' ? lastMessage.content : 'Извините, не удалось сформировать ответ.',
|
||
success: true
|
||
};
|
||
|
||
} catch (error) {
|
||
console.error('Ошибка при обработке сообщения:', error);
|
||
return {
|
||
content: 'Извините, произошла ошибка при обработке вашего запроса. Попробуйте позже.',
|
||
success: false,
|
||
error: error instanceof Error ? error.message : 'Неизвестная ошибка'
|
||
};
|
||
}
|
||
}
|
||
|
||
public async clearHistory(): Promise<void> {
|
||
this.memorySaver = new MemorySaver();
|
||
|
||
const tools = [
|
||
new SupportContextTool(this.userId),
|
||
new KnowledgeBaseTool()
|
||
];
|
||
|
||
this.agent = createReactAgent({
|
||
llm: this.llm,
|
||
tools: tools,
|
||
checkpointSaver: this.memorySaver
|
||
});
|
||
|
||
this.isFirstMessage = true;
|
||
}
|
||
}
|