如何處理未產生查詢的情況
有時,查詢分析技術可能會允許產生任意數量的查詢 - 包括不產生任何查詢!在這種情況下,我們的整體鏈需要檢查查詢分析的結果,然後再決定是否呼叫檢索器。
我們將在本範例中使用模擬資料。
設定
安裝依賴套件
%pip install -qU langchain langchain-community langchain-openai langchain-chroma
Note: you may need to restart the kernel to use updated packages.
設定環境變數
在本範例中,我們將使用 OpenAI
import getpass
import os
if "OPENAI_API_KEY" not in os.environ:
os.environ["OPENAI_API_KEY"] = getpass.getpass()
# Optional, uncomment to trace runs with LangSmith. Sign up here: https://smith.langchain.com.
# os.environ["LANGSMITH_TRACING"] = "true"
# os.environ["LANGSMITH_API_KEY"] = getpass.getpass()
建立索引
我們將在虛假資訊上建立向量儲存庫。
from langchain_chroma import Chroma
from langchain_openai import OpenAIEmbeddings
from langchain_text_splitters import RecursiveCharacterTextSplitter
texts = ["Harrison worked at Kensho"]
embeddings = OpenAIEmbeddings(model="text-embedding-3-small")
vectorstore = Chroma.from_texts(
texts,
embeddings,
)
retriever = vectorstore.as_retriever()
查詢分析
我們將使用函式呼叫來結構化輸出。但是,我們將配置 LLM,使其不需要呼叫代表搜尋查詢的函式(如果它決定不呼叫)。然後,我們也將使用提示來進行查詢分析,明確說明何時應該以及何時不應該進行搜尋。
from typing import Optional
from pydantic import BaseModel, Field
class Search(BaseModel):
"""Search over a database of job records."""
query: str = Field(
...,
description="Similarity search query applied to job record.",
)
from langchain_core.prompts import ChatPromptTemplate
from langchain_core.runnables import RunnablePassthrough
from langchain_openai import ChatOpenAI
system = """You have the ability to issue search queries to get information to help answer user information.
You do not NEED to look things up. If you don't need to, then just respond normally."""
prompt = ChatPromptTemplate.from_messages(
[
("system", system),
("human", "{question}"),
]
)
llm = ChatOpenAI(model="gpt-4o-mini", temperature=0)
structured_llm = llm.bind_tools([Search])
query_analyzer = {"question": RunnablePassthrough()} | prompt | structured_llm
我們可以看見,透過調用此功能,我們會收到一個訊息,該訊息有時(但並非總是)會傳回工具呼叫。
query_analyzer.invoke("where did Harrison Work")
AIMessage(content='', additional_kwargs={'tool_calls': [{'id': 'call_korLZrh08PTRL94f4L7rFqdj', 'function': {'arguments': '{"query":"Harrison"}', 'name': 'Search'}, 'type': 'function'}], 'refusal': None}, response_metadata={'token_usage': {'completion_tokens': 14, 'prompt_tokens': 95, 'total_tokens': 109}, 'model_name': 'gpt-4o-mini-2024-07-18', 'system_fingerprint': 'fp_483d39d857', 'finish_reason': 'tool_calls', 'logprobs': None}, id='run-ea94d376-37bf-4f80-abe6-e3b42b767ea0-0', tool_calls=[{'name': 'Search', 'args': {'query': 'Harrison'}, 'id': 'call_korLZrh08PTRL94f4L7rFqdj', 'type': 'tool_call'}], usage_metadata={'input_tokens': 95, 'output_tokens': 14, 'total_tokens': 109})
query_analyzer.invoke("hi!")
AIMessage(content='Hello! How can I assist you today?', additional_kwargs={'refusal': None}, response_metadata={'token_usage': {'completion_tokens': 10, 'prompt_tokens': 93, 'total_tokens': 103}, 'model_name': 'gpt-4o-mini-2024-07-18', 'system_fingerprint': 'fp_483d39d857', 'finish_reason': 'stop', 'logprobs': None}, id='run-ebdfc44a-455a-4ca6-be85-84559886b1e1-0', usage_metadata={'input_tokens': 93, 'output_tokens': 10, 'total_tokens': 103})
使用查詢分析進行檢索
那麼我們該如何將其包含在鏈中呢?讓我們看看下面的範例。
from langchain_core.output_parsers.openai_tools import PydanticToolsParser
from langchain_core.runnables import chain
output_parser = PydanticToolsParser(tools=[Search])
API 參考:PydanticToolsParser | chain
@chain
def custom_chain(question):
response = query_analyzer.invoke(question)
if "tool_calls" in response.additional_kwargs:
query = output_parser.invoke(response)
docs = retriever.invoke(query[0].query)
# Could add more logic - like another LLM call - here
return docs
else:
return response
custom_chain.invoke("where did Harrison Work")
Number of requested results 4 is greater than number of elements in index 1, updating n_results = 1
[Document(page_content='Harrison worked at Kensho')]
custom_chain.invoke("hi!")
AIMessage(content='Hello! How can I assist you today?', additional_kwargs={'refusal': None}, response_metadata={'token_usage': {'completion_tokens': 10, 'prompt_tokens': 93, 'total_tokens': 103}, 'model_name': 'gpt-4o-mini-2024-07-18', 'system_fingerprint': 'fp_483d39d857', 'finish_reason': 'stop', 'logprobs': None}, id='run-e87f058d-30c0-4075-8a89-a01b982d557e-0', usage_metadata={'input_tokens': 93, 'output_tokens': 10, 'total_tokens': 103})