在构建基于 SQL 的问答系统时,我们经常会遇到一类棘手的问题 —— 高基数列中的专有名词拼写错误。比如用户想查询 "Alice In Chains" 的专辑数量,却可能误输入 "Alis In Chains"。这类问题之所以难处理,是因为高基数列(如艺术家名称、歌曲标题等)包含大量唯一值,传统的精确匹配查询在面对拼写错误时几乎失效。今天我们就来聊聊如何通过向量存储技术,让智能代理具备 "纠错能力",精准识别用户意图。

一、问题本质:高基数列与专有名词的天然矛盾

高基数列的典型特征是唯一值数量大,比如音乐数据库中的 "Artist.Name" 列可能包含上万种不同的艺术家名称。当用户输入存在拼写错误时,直接使用 SQL 进行WHERE Name = '错误拼写'查询必然返回空结果。而这类专有名词(如人名、地名、作品名)的特点是需要严格精确匹配,差一个字母就可能指向完全不同的实体。

传统解决方案(如模糊查询LIKE)存在两个缺陷:

  1. 效率低下:高基数列上的模糊查询会扫描大量数据,影响性能
  2. 准确性差:无法区分语义相似但拼写不同的专有名词(如 "AC/DC" 和 "ACDC")

我们需要一种既能处理拼写错误,又能保持高查询精度的方法,向量存储技术正是解决这个问题的关键。

二、核心方案:向量存储实现智能纠错

1. 数据预处理:提取唯一专有名词

首先需要从数据库中提取高基数列的唯一值列表。我们编写query_as_list函数完成三个核心操作:

python

import ast
import re

def query_as_list(db, query):
    # 1. 执行SQL查询并解析结果
    res = db.run(query)  # 返回字符串形式的查询结果,如"[(('AC/DC',),), (('Alice In Chains',),)]"
    structured_res = ast.literal_eval(res)  # 转换为嵌套列表结构
    
    # 2. 清洗数据:去除数字、空白符,提取唯一值
    flat_res = [el[0] for sublist in structured_res for el in sublist if el]  # 展平嵌套结构
    cleaned_res = [re.sub(r"\b\d+\b", "", s).strip() for s in flat_res]  # 删除孤立数字
    
    # 3. 去重并返回唯一值列表
    return list(set(cleaned_res))  # 利用集合特性去除重复值

# 提取艺术家和专辑名称
artists = query_as_list(db, "SELECT Name FROM Artist")
albums = query_as_list(db, "SELECT Title FROM Album")

这个函数解决了三个关键问题:

  • 结果解析:使用ast.literal_eval安全解析数据库返回的字符串化列表
  • 数据清洗:通过正则表达式去除无关数字(如某些名称中的年份后缀)
  • 去重处理:确保后续向量存储中没有冗余数据

2. 构建向量存储:让专有名词可计算

我们使用 Ollama 的 LLaMA3 模型生成文本嵌入,将每个专有名词转换为向量:

python

from langchain_ollama import OllamaEmbeddings
from langchain_core.vectorstores import InMemoryVectorStore

# 初始化嵌入模型
embeddings = OllamaEmbeddings(model="llama3")  # 选择支持长文本的高性能模型

# 创建向量存储并添加数据
vector_store = InMemoryVectorStore(embeddings)
vector_store.add_texts(artists + albums)  # 将艺术家和专辑名称统一存入向量库

向量存储的核心优势在于语义相似度计算

  • 即使 "Alice In Chains" 被误写为 "Alis In Chains",它们的向量在高维空间中依然接近
  • 通过余弦相似度计算,可以快速找到最接近的正确专有名词

3. 创建检索工具:赋能代理纠错能力

我们将向量存储封装为search_proper_nouns工具,告诉代理 "遇到专有名词过滤时必须先查向量库":

python

from langchain.agents.agent_toolkits import create_retriever_tool

# 配置检索参数:返回最相似的5个结果
retriever = vector_store.as_retriever(search_kwargs={"k": 5})

# 创建工具并定义使用规则
description = (
    "用于查找过滤用的专有名词。输入是近似拼写的名称,输出是数据库中有效的专有名词,"
    "请返回与搜索词最相似的那个专有名词。"
)
retriever_tool = create_retriever_tool(retriever, "search_proper_nouns", description)

这个工具的关键作用是建立用户输入与数据库真实值的桥梁

  • 代理在生成 SQL 查询前,会先调用此工具验证专有名词的正确性
  • 即使输入存在拼写错误,也能通过向量匹配找到正确值

三、整合到智能代理:构建完整纠错流程

1. 扩展工具集与系统提示

将检索工具添加到 SQL 代理的工具列表,并通过系统提示强化使用规则:

python

from langchain_community.agent_toolkits import SQLDatabaseToolkit

# 初始化原有的SQL工具集
toolkit = SQLDatabaseToolkit(db=db, llm=llm)
tools = toolkit.get_tools()

# 添加专有名词检索工具
tools.append(retriever_tool)

# 更新系统提示,强制要求使用检索工具
system_prompt = f"""
{原系统提示}

重要规则:当需要根据名称(如Artist.Name、Album.Title)进行过滤时,
必须先使用'search_proper_nouns'工具查找正确的专有名词,
禁止直接使用用户输入的名称构建查询!
"""

2. 代理执行流程解析

当用户提问 "How many albums does alis in chain have?" 时,代理会按以下步骤执行:

  1. 识别专有名词:检测到 "alis in chain" 可能是艺术家名称
  2. 调用检索工具:向向量库查询最相似的名称,返回 "Alice In Chains"
  3. 构建正确查询:根据正确名称生成 SQL:

    sql

    SELECT COUNT(*) FROM Album 
    WHERE ArtistId = (SELECT ArtistId FROM Artist WHERE Name = 'Alice In Chains')
    
  4. 执行并返回结果:通过正确查询获取专辑数量

整个过程中,代理通过 **"用户输入→向量检索→生成查询"** 的闭环,将拼写错误的影响降到最低。

四、关键技术点解析

1. 为什么选择 InMemoryVectorStore?

  • 轻量级实现:适合小规模数据集(如几万条专有名词),无需复杂部署
  • 内存级速度:检索操作在内存中完成,响应时间毫秒级,适合实时问答场景
  • 无缝集成:与 LangChain 工具集天然兼容,无需额外适配

2. 检索工具的描述设计技巧

工具描述中强调 "必须返回最相似的专有名词",引导代理优先选择最接近的唯一值,避免返回多个候选造成歧义。这通过search_kwargs={"k": 5}和后续逻辑处理实现 —— 虽然检索时返回前 5 个相似值,但工具最终只保留最相似的第一个作为结果。

3. 数据清洗的必要性

去除数字和空白符是关键预处理步骤:

  • 有些专有名词可能包含版本号(如 "Track 1.0"),需要去除数字保留核心名称
  • 统一格式(如去除前后空格)可以避免 "Alice In Chains" 和 "Alice In Chains" 被视为不同值

五、总结:打造鲁棒的 SQL 问答系统

通过向量存储处理高基数列的专有名词问题,我们解决了传统方法的两大痛点:

  • 准确性:利用语义相似度匹配,容忍一定程度的拼写错误
  • 效率:预处理阶段构建向量库,查询阶段通过内存检索快速纠错

这套方案的核心价值在于让机器理解人类输入的 "不完美",在用户输入与数据库精确匹配之间搭建了智能桥梁。如果你正在开发数据驱动的问答系统,尤其是涉及大量专有名词的场景(如电商商品名称、生物物种名称等),不妨尝试引入向量存储技术。

记得在实际应用中根据数据规模选择合适的向量数据库(如 Pinecone、Milvus),并定期更新专有名词列表以保证数据新鲜度。觉得有帮助的话,欢迎收藏本文,后续我们会分享更多复杂查询优化技巧!

Logo

魔乐社区(Modelers.cn) 是一个中立、公益的人工智能社区,提供人工智能工具、模型、数据的托管、展示与应用协同服务,为人工智能开发及爱好者搭建开放的学习交流平台。社区通过理事会方式运作,由全产业链共同建设、共同运营、共同享有,推动国产AI生态繁荣发展。

更多推荐