Как сохранить историю чата с помощью цепочки langchain talkalRetrivalQA в приложении Next JS?
Я создаю чат-бота для контроля качества текстового документа, использую Langchainjs вместе с OpenAI LLM для создания вложений, а также Chat и Pinecone в качестве векторного хранилища.
После успешной загрузки вложений и создания индекса на шишке. Я использую приложение Next JS для связи с OpenAI и Pinecone.
Текущая структура моего приложения выглядит так:
1: Интерфейс -> пользователь вводитquestion
и выполняет POST-вызов к маршруту API сервера NEXT js./ask
2: Функция сервера выглядит следующим образом:
const vectorStore = await PineconeStore.fromExistingIndex(
new OpenAIEmbeddings(),
{ pineconeIndex })
const model = new ChatOpenAI({ temperature: 0.5, modelName: 'gpt-3.5-turbo' })
const memory = new ConversationSummaryMemory({
memoryKey: 'chat_history',
llm: new ChatOpenAI({ modelName: 'gpt-3.5-turbo', temperature: 0 }),
})
const chain = ConversationalRetrievalQAChain.fromLLM(
model,
vectorStore.asRetriever(),
{
memory,
}
)
const result = await chain.call({
question,
})
return NextResponse.json({ data: result.text })
ПРОБЛЕМА: Чат-бот никогда не имеет доступа к какой-либо истории, потому что в памяти всегда хранится ТОЛЬКО последнее сообщение.
console.log('memory:', await memory.loadMemoryVariables({}))
я тоже попробовалBufferMemory
и та же проблема: в буфере памяти есть ТОЛЬКО только что запрошенное сообщение. Если в буфер поступает новый запрос, буфер очищается, и новый запрос является единственным сообщением в памяти.
Возможно, мне неясно, как правильно хранить историю, чтобыconst result = await chain.call({question,})
звонок имеет доступ к предыдущей информации
ОБНОВЛЕНИЕ : Я успешно использовал память чата, поддерживаемую Upstash Redis, с langchain, однако все еще интересно, можно ли хранить сообщения с помощью пользовательского браузера?
2 ответа
Я думаю, вам следует использовать свойствоConversationSummaryMemory
:
const memory = new ConversationSummaryMemory({
memoryKey: 'chat_history',
llm: new ChatOpenAI({ modelName: 'gpt-3.5-turbo', temperature: 0 }),
returnMessages:true
})
это код дляloadMemoryVariables
от
async loadMemoryVariables(_) {
if (this.returnMessages) {
const result = {
[this.memoryKey]: [new this.summaryChatMessageClass(this.buffer)],
};
return result;
}
const result = { [this.memoryKey]: this.buffer };
return result;
}
если ты установишьreturnMessages:true
оно вернетсяthis.summaryChatMessageClass(this.buffer)
объект, в противном случае он просто возвращает строку.
Я использую тот же стек, что и вы (Next.js, Pinecone, Langchain ConversationalRetrivalQAChain), и некоторое время боролся именно с этой проблемой.
В конце концов я прибегнул к приведенному ниже «хаку», который действительно работает, по сути фиксируя историю в видеmessages
массив, который я помещаю в конец приглашения. Насколько мне известно, это не сильно отличается от того, как должны работать компоненты «Память» LangChain, поэтому я не чувствую себя ужасно, делая это.
Вот урезанная версия моей основной функции-обработчика. Обратите внимание на строку, начинающуюся сqueryText+='\nIf necessary ...
export async function POST(req: Request) {
const { messages } = await req.json();
let queryText = messages[messages.length - 1].content;
queryText+='\nIf necessary, utilize the below chat history as additional context:'+JSON.stringify(messages);
const chain = ConversationalRetrievalQAChain.fromLLM(
streamingModel,
vectorStore.asRetriever(),
{
returnSourceDocuments: true,
questionGeneratorChainOptions: {
llm: nonStreamingModel,
},
}
const { stream, handlers } = LangChainStream();
chain.call({ question: queryText }, [handlers]).catch(console.error)
return new StreamingTextResponse(stream);
}