Как объединить ConversationalRetrivalQAChain, агенты и инструменты в LangChain
Я хотел бы объединить, например, инструмент в LangChain.
я используюConversationalRetrievalQAChain
для поиска в PDF-файлах продуктов, которые были загружены с использованием API встраивания OpenAI и локальной базы данных векторов цветности. Это работает нормально. Однако PDF-файлы продукта не содержат актуальной информации о ценах. Поэтому, когда пользователь запрашивает информацию о ценах, я бы хотел, чтобы LangChain использовал этот инструмент для поиска цены в Google. У меня обе части работают отдельно, но я бы хотел их объединить.
Вот фрагмент поиска документов (имейте в виду: это код PoC-качества):
// Prompt used to rephrase/condose the question
const CONDENSE_PROMPT = `Given the following conversation and a follow up question, rephrase the follow up question to be a standalone question.
Chat History:
{chat_history}
Follow Up Input: {question}
Standalone question:`;
// Prompt for the actual question
const QA_PROMPT = `You are a helpful AI assistant for sales reps to answer questions about product features and technicals specifications.
Use the following pieces of context to answer the question at the end.
If you don't know the answer, just say you don't know. DO NOT try to make up an answer.
If the question is not related to the context, politely respond that you are tuned to only answer questions that are related to the context.
{context}
Question: {question}
Helpful answer:`;
export const POST: RequestHandler = async ({ request }) => {
const { messages } = await request.json();
const { stream, handlers } = LangChainStream();
const openAIApiKey = OPENAI_API_KEY;
const embeddings = new OpenAIEmbeddings({ openAIApiKey });
// This model is used to answer the actual question
const model = new ChatOpenAI({
openAIApiKey,
temperature: 0,
streaming: true,
});
// This model is used to rephrase the question based on the chat history
const nonStreamingModel = new ChatOpenAI({
openAIApiKey,
temperature: 0,
});
const store = await Chroma.fromExistingCollection(embeddings, {
collectionName: 'langchain',
});
const chain = ConversationalRetrievalQAChain.fromLLM(
model,
store.asRetriever(),
{
returnSourceDocuments: true,
verbose: false,
qaChainOptions: {
type: "stuff",
prompt: PromptTemplate.fromTemplate(QA_PROMPT)
},
questionGeneratorChainOptions: {
template: CONDENSE_PROMPT,
llm: nonStreamingModel,
},
}
);
const callbacks = CallbackManager.fromHandlers(handlers);
const latest = (messages as Message[]).at(-1)!.content;
chain.call({ question: latest, chat_history: (messages as Message[]).map((m) => `${m.role}: ${m.content}`).join('\n') }, callbacks).catch(console.error);
return new StreamingTextResponse(stream);
};
ЭтоSerpAPI
код инструмента:
export const POST: RequestHandler = async ({ request }) => {
const { messages } = await request.json();
const { stream, handlers } = LangChainStream();
const openAIApiKey = OPENAI_API_KEY;
// This model is used to answer the actual question
const model = new ChatOpenAI({
openAIApiKey,
temperature: 0,
streaming: true,
});
// Define the list of tools the agent can use
const tools = [
new SerpAPI(SERPAPI_API_KEY, {
location: "Austin,Texas,United States",
hl: "en",
gl: "us",
}),
];
// Create the agent from the chat model and the tools
const agent = ChatAgent.fromLLMAndTools(model, tools);
// Create an executor, which calls to the agent until an answer is found
const executor = AgentExecutor.fromAgentAndTools({ agent, tools });
const callbacks = CallbackManager.fromHandlers(handlers);
const latest = (messages as Message[]).at(-1)!.content;
executor.call({ input: latest }, callbacks).catch(console.error);
return new StreamingTextResponse(stream);
};
Сами по себе они работают нормально. Как мне их объединить?
Это рабочий процесс, который я себе представляю:
- Поступает вопрос пользователя.
- LangChain решает, требует ли этот вопрос поиска в Интернете или нет.
- Если это так, используйте инструмент SerpAPI для поиска и ответа.
- Если поиск в Интернете не требуется, извлеките аналогичные фрагменты из векторной базы данных, создайте подсказку и запросите OpenAI.
- Любой путь должен оказаться в истории чата, и, возможно, в любом случае следует использовать историю чата, чтобы пользователь мог спросить: «Сколько стоит?» а подразумеваемый продукт можно узнать на основе истории чата.
Это возможно? Спасибо!
1 ответ
Мой хороший друг Джастин указал мне правильное направление. В LangChain есть «Агенты поиска». Идея состоит в том, что ретривер на основе векторной базы данных — это просто еще один инструмент, доступный LLM. Итак, в моем примере у вас будет один «инструмент» для получения соответствующих данных и другой «инструмент» для выполнения поиска в Интернете. На основании данных пользователя LLM выберет, какой инструмент использовать.
Более подробная информация и пример кода здесь: https://js.langchain.com/docs/use_cases/question_answering/conversational_retrieval_agents .