如何应对高基数分类数据进行查询分析

89 阅读3分钟
## 引言

在数据分析中,处理高基数的分类变量是一项挑战,尤其是在执行查询分析时。当使用大语言模型(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---