## 引言
在数据分析中,处理高基数的分类变量是一项挑战,尤其是在执行查询分析时。当使用大语言模型(LLM)生成查询时,需要确保生成的查询精确匹配类别值。随着有效类别的增加,确保模型正确生成值变得更加困难。在本篇文章中,我们将探讨如何有效处理这一问题。
## 主要内容
### 1. 理解问题背景
高基数分类数据指的是类别数量非常多的数据集。在执行查询分析时,可能需要根据这些类别进行精确过滤。然而,这对LLM来说是一项挑战,因为过多的类别可能超过其上下文窗口的限制,导致模型不能有效地关注所有信息。
### 2. 基础设置
我们将使用LangChain和OpenAI的API来进行演示。请确保已安装必要的依赖并设置环境变量以使用OpenAI的API。
```python
# 安装依赖
# %pip install -qU langchain langchain-community langchain-openai faker langchain-chroma
# 设置环境变量
import getpass
import os
os.environ["OPENAI_API_KEY"] = getpass.getpass() # 使用API代理服务提高访问稳定性
3. 数据生成
使用Faker库生成模拟数据,便于演示。
from faker import Faker
fake = Faker()
names = [fake.name() for _ in range(10000)]
4. 查询分析初步
我们首先通过定义基本的查询分析流程来理解问题。
from langchain_core.pydantic_v1 import BaseModel
from langchain_core.prompts import ChatPromptTemplate
from langchain_core.runnables import RunnablePassthrough
from langchain_openai import ChatOpenAI
class Search(BaseModel):
query: str
author: str
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
5. 添加所有可能值
一种方法是将所有可能的类别值加入提示中。但若类别数过多,可能导致上下文窗口超限。
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
6. 利用索引优化查询
创建索引以处理高基数数据,减少查询时需要处理的类别数量。
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
7. 替换方法
使用Pydantic类的校验器将LLM生成的值替换为最接近的有效值。
from langchain_core.pydantic_v1 import validator
class Search(BaseModel):
query: str
author: str
@validator("author")
def correct_author(cls, v: str) -> str:
return vectorstore.similarity_search(v, k=1)[0].page_content
corrective_structure_llm = llm.with_structured_output(Search)
corrective_query_analyzer = (
{"question": RunnablePassthrough()} | prompt | corrective_structure_llm
)
常见问题和解决方案
- 上下文长度超限:使用索引减少需要处理的类别数。
- 生成错误的类别值:通过后处理替换生成值或在提示中限制值列表。
总结和进一步学习资源
处理高基数分类数据时,需要仔细考虑LLM的上下文限制。使用索引和后处理是有效的策略。进一步学习可以参考以下资源:
参考资料
如果这篇文章对你有帮助,欢迎点赞并关注我的博客。您的支持是我持续创作的动力!
---END---