import type { BaseChatModel } from '@langchain/core/language_models/chat_models'; import type { BaseMessage } from '@langchain/core/messages'; import { AIMessage, HumanMessage } from '@langchain/core/messages'; import { PromptTemplate } from '@langchain/core/prompts'; import z from 'zod'; const compactPromptTemplate = PromptTemplate.fromTemplate( `Please summarize the following conversation between a user and an AI assistant building an n8n workflow: {previousSummary} {conversationText} Provide a structured summary that captures the key points, decisions made, current state of the workflow, and suggested next steps.`, ); export async function conversationCompactChain( llm: BaseChatModel, messages: BaseMessage[], previousSummary: string = '', ) { // Use structured output for consistent summary format const CompactedSession = z.object({ summary: z.string().describe('A concise summary of the conversation so far'), key_decisions: z.array(z.string()).describe('List of key decisions and actions taken'), current_state: z.string().describe('Description of the current workflow state'), next_steps: z.string().describe('Suggested next steps based on the conversation'), }); const modelWithStructure = llm.withStructuredOutput(CompactedSession); // Format messages for summarization const conversationText = messages .map((msg) => { if (msg instanceof HumanMessage) { // eslint-disable-next-line @typescript-eslint/no-base-to-string, @typescript-eslint/restrict-template-expressions return `User: ${msg.content}`; } else if (msg instanceof AIMessage) { if (typeof msg.content === 'string') { return `Assistant: ${msg.content}`; } else { return 'Assistant: Used tools'; } } return ''; }) .filter(Boolean) .join('\n'); const compactPrompt = await compactPromptTemplate.invoke({ previousSummary, conversationText, }); const structuredOutput = await modelWithStructure.invoke(compactPrompt); const formattedSummary = `## Previous Conversation Summary **Summary:** ${structuredOutput.summary} **Key Decisions:** ${(structuredOutput.key_decisions as string[]).map((d: string) => `- ${d}`).join('\n')} **Current State:** ${structuredOutput.current_state} **Next Steps:** ${structuredOutput.next_steps}`; return { success: true, summary: structuredOutput, summaryPlain: formattedSummary, }; }