高基数分类查询解析的实用方法与挑战
在处理数据分析任务时,高基数的分类变量常常带来挑战。尤其是在做查询解析想要在分类列上创建筛选条件时,通常需要指定精确的分类值。当有效值数量很少时,通过提示生成这些值相对简单。然而,当有效值数量很多时,这些值可能无法全部放入大语言模型(LLM)的上下文中,或者即便放入也可能太多,导致模型无法有效地处理。
在这篇文章中,我们将探讨如何应对这一挑战。
设置
安装依赖
首先,我们需要安装相关依赖(请确保你的Python环境中已安装这些库):
# %pip install -qU langchain langchain-community langchain-openai faker langchain-chroma
设置环境变量
我们将使用OpenAI的API,在使用前需要设置API密钥:
import getpass
import os
os.environ["OPENAI_API_KEY"] = getpass.getpass()
设置数据
我们将使用Faker库生成一些假数据作为示例:
from faker import Faker
fake = Faker()
names = [fake.name() for _ in range(10000)]
查询解析
我们来设置一个基准的查询解析模型:
from langchain_core.pydantic_v1 import BaseModel, Field
class Search(BaseModel):
query: str
author: str
from langchain_core.prompts import ChatPromptTemplate
from langchain_core.runnables import RunnablePassthrough
from langchain_openai import ChatOpenAI
system = """Generate a relevant search query for a library system"""
prompt = ChatPromptTemplate.from_messages(
[
("system", system),
("human", "{question}"),
]
)
llm = ChatOpenAI(model="gpt-3.5-turbo-0125", temperature=0)
structured_llm = llm.with_structured_output(Search)
query_analyzer = {"question": RunnablePassthrough()} | prompt | structured_llm
挑战与解决方案
精确匹配问题
如果我们精确拼写名字,模型可以正确处理:
query_analyzer.invoke("what are books about aliens by Jesse Knight")
# Search(query='books about aliens', author='Jesse Knight')
但是,如果拼写不够精确,解析可能出现错误:
query_analyzer.invoke("what are books about aliens by jess knight")
# Search(query='books about aliens', author='Jess Knight')
添加所有可能值
一个策略是将所有可能的值添加到提示中:
system = """Generate a relevant search query for a library system.
`author` attribute MUST be one of:
{authors}
Do NOT hallucinate author name!"""
base_prompt = ChatPromptTemplate.from_messages(
[
("system", system),
("human", "{question}"),
]
)
prompt = base_prompt.partial(authors=", ".join(names))
query_analyzer_all = {"question": RunnablePassthrough()} | prompt | structured_llm
然而,如果列表太长,可能导致上下文超出模型的限制。
使用向量索引选择相关值
一个更有效的策略是为相关值创建索引,然后查询最相关的N个值。
from langchain_chroma import Chroma
from langchain_openai import OpenAIEmbeddings
embeddings = OpenAIEmbeddings(model="text-embedding-3-small")
vectorstore = Chroma.from_texts(names, embeddings, collection_name="author_names")
def select_names(question):
_docs = vectorstore.similarity_search(question, k=10)
_names = [d.page_content for d in _docs]
return ", ".join(_names)
create_prompt = {
"question": RunnablePassthrough(),
"authors": select_names,
} | base_prompt
query_analyzer_select = create_prompt | structured_llm
替换后选择
另一种方法是让LLM生成任意值,然后将其转换为有效值:
from langchain_core.pydantic_v1 import validator
class Search(BaseModel):
query: str
author: str
@validator("author")
def double(cls, v: str) -> str:
return vectorstore.similarity_search(v, k=1)[0].page_content
system = """Generate a relevant search query for a library system"""
prompt = ChatPromptTemplate.from_messages(
[
("system", system),
("human", "{question}"),
]
)
corrective_structure_llm = llm.with_structured_output(Search)
corrective_query_analyzer = (
{"question": RunnablePassthrough()} | prompt | corrective_structure_llm
)
总结和进一步学习资源
处理高基数的分类查询需要考虑上下文限制和匹配准确性。通过结合向量索引和验证技术,可以更精确地提取和匹配数据。推荐的进一步学习资源包括:
参考资料
- LangChain GitHub 仓库: github.com/hwchase17/l…
- Faker Python Library: github.com/joke2k/fake…
如果这篇文章对你有帮助,欢迎点赞并关注我的博客。您的支持是我持续创作的动力!
---END---