1. 项目概述:当大模型遇上企业级数据查询
最近在跟几个做企业数据中台的朋友聊天,大家普遍头疼一个问题:业务部门的需求千变万化,今天要个销售漏斗分析,明天要个用户行为洞察。每次提需求,数据团队就得吭哧吭哧写SQL,业务同学还得等。等SQL写好了,业务场景可能又变了。有没有一种方法,能让业务同学用最自然的语言描述需求,系统就能自动、准确、安全地生成可执行的SQL,并且这个过程是可控、可解释、可优化的?
这正是“ProSPy: A Profiling-Driven SQL-Python Agentic Framework for Enterprise Text-to-SQL”这个项目要啃的硬骨头。简单说,它想打造一个面向企业级应用的、智能的“自然语言转SQL”的智能体框架。但和市面上很多玩具级的、基于单一提示词的方案不同,ProSPy的核心思路非常“工程化”——它引入了“Profiling-Driven”(画像驱动)和“Agentic Framework”(智能体框架)这两个关键设计。
“Profiling-Driven”意味着它不是把用户的自然语言描述直接扔给大模型就完事了。相反,它会先对目标数据库进行一番“体检”,生成一份详细的“数据画像”。这份画像包括表结构、字段含义、数据分布、关联关系,甚至业务常用查询模式。有了这份画像作为上下文,大模型生成SQL的准确率和合理性会大幅提升。“Agentic Framework”则说明它不是一个单一模型,而是一个由多个分工明确的“智能体”协同工作的系统。比如,可能有智能体负责理解用户意图,有智能体负责检索相关数据画像,有智能体负责生成SQL草稿,还有智能体负责对生成的SQL进行安全检查、性能评估和优化建议。
这个框架的价值在于,它试图将Text-to-SQL从一个“黑盒魔法”变成一个“白盒工程”。对于企业而言,可控性、安全性和可解释性,远比单纯的“能跑通”更重要。它适合那些拥有复杂数据仓库、希望提升数据分析效率,同时又对数据安全与查询质量有高标准要求的技术团队和数据产品经理。接下来,我们就深入拆解一下,要构建这样一个框架,背后的核心思路、技术选型以及那些必须趟过去的“坑”。
2. 核心架构与设计哲学
构建一个企业级的Text-to-SQL框架,远不是调用一个API那么简单。它需要一套严谨的架构来平衡灵活性、准确性、安全性和性能。ProSPy提出的“画像驱动”和“智能体框架”是它的两大支柱,这背后体现的是一种系统性的工程思维。
2.1 为何是“画像驱动”而非“直接提示”
很多初代的Text-to-SQL尝试,其提示词(Prompt)结构可能是这样的:“你是一个SQL专家,请根据以下表结构(DDL),将用户问题‘查询上个月销售额超过100万的客户’转化为SQL。” 这种方法在表结构简单时或许有效,但在企业真实场景下,弊端立现:
- 缺乏上下文:大模型不知道“销售额”对应哪个字段(是
sales_amount还是revenue?),不知道“客户”表的主键和外键如何关联订单表。 - 忽略数据特性:如果“销售额”字段中存在大量NULL值或异常值,直接使用
> 1000000可能会漏掉数据或产生错误。 - 不懂业务逻辑:“上个月”是指自然月还是财务月?是否有特定的状态过滤(如只计算‘已支付’订单)?这些业务规则很难仅从DDL中获取。
“画像驱动”就是为了解决这些问题。它要求在系统初始化或定期运行时,对数据库进行主动分析,生成一份结构化的元数据“画像”。这份画像通常包括:
- 结构画像:基础的DDL,包括表名、列名、数据类型、主键、外键、索引。
- 统计画像:通过执行
ANALYZE或类似命令,获取每列的数值分布(最小值、最大值、平均值、中位数、唯一值数量)、数据倾斜情况。这对于生成合理的WHERE条件(例如,避免对唯一值极少的列使用=查询)和JOIN选择至关重要。 - 语义画像:通过读取数据字典、注释(COMMENT),或利用小模型对列名进行意图识别,为字段附加业务标签。例如,将
cust_id标记为“客户标识符”,order_date标记为“订单创建日期”。 - 关联画像:基于外键和查询日志,分析出表与表之间高频的关联路径。当用户查询涉及多个实体时,系统能优先选择最合理、最高效的关联方式。
- 查询模式画像:分析历史SQL日志,总结出常见的过滤条件组合、聚合维度、排序方式。这可以作为大模型生成SQL时的“最佳实践”参考。
有了这份丰富的画像,给大模型的提示词就变成了:“基于以下详细的数据库画像(包含结构、统计、语义信息),请将用户问题转化为SQL。特别注意:在orders表中,status字段的常见值包括‘paid’,‘pending’,‘cancelled’,业务上通常只关心‘paid’状态的订单进行销售额统计。” 这样,生成的SQL自然更贴近业务实际。
2.2 智能体框架的分工与协作
“智能体”在这里不是指一个具有长期记忆和规划能力的通用AI,而是指一个具有特定职能、可被调度执行的模块化组件。ProSPy的智能体框架通常包含以下角色:
意图解析智能体:接收用户原始输入(如“帮我看看华东区最近一周的销售TOP10产品”)。它的任务不是生成SQL,而是进行“任务分解”和“语义澄清”。它可能输出结构化信息:
{“核心意图”: “排名查询”, “维度”: [“产品”], “度量”: [“销售额”], “过滤条件”: {“区域”: “华东”, “时间”: “最近7天”}, “排序”: {“字段”: “销售额”, “方向”: “DESC”}, “限制”: 10}。这个智能体可以利用一个小型的、微调过的自然语言理解模型,或者通过规则+关键词匹配实现。画像检索与上下文构建智能体:根据意图解析的结果,从全局数据画像库中,精准检索出相关的表、字段、关联关系、统计信息。例如,识别出“区域”对应
dim_region.region_name,“产品”对应dim_product.product_name,“销售额”对应fact_sales.sales_amount。然后,它将检索到的碎片化画像信息,组织成一段连贯、高质量的上下文描述,准备喂给SQL生成智能体。这个环节是精度和效率的关键,可能需要用到向量数据库进行语义检索。SQL生成智能体:这是核心,通常由一个能力强的大语言模型(如GPT-4、Claude 3或开源的CodeLlama)担任。它接收“用户意图结构化描述”和“精炼后的数据库画像上下文”,输出符合数据库语法的SQL语句。提示词工程在这里至关重要,需要明确指令格式、输出规范(如必须使用别名、必须包含必要的
JOIN条件)。SQL验证与安全智能体:生成的SQL不能直接执行。这个智能体负责进行静态检查:
- 语法验证:通过数据库驱动或SQL解析器检查语法是否正确。
- 权限沙箱检查:模拟一个具有最小权限的账户,检查SQL是否试图访问未授权的表或执行
DROP、DELETE等危险操作。这是企业级应用的底线。 - 逻辑合理性初筛:检查是否缺少必要的
WHERE条件导致笛卡尔积,是否在GROUP BY中使用了不合适的字段等。
SQL优化与执行智能体:对于通过验证的SQL,这个智能体可以(可选地)对其进行优化。它可以利用画像中的统计信息,建议添加缺失的索引、重写子查询为
JOIN、调整条件顺序。然后,它在可控的环境(如连接池、超时设置、资源限制)下执行SQL,并捕获执行计划、耗时和结果集大小。结果解释与可视化建议智能体:将执行返回的数据结果,再次用自然语言进行总结(“华东区最近一周销售额最高的产品是XXX,总计YYY元”),并可能根据结果类型(时间序列、类别对比、分布)建议最合适的图表类型。这完成了从“问”到“答”再到“看”的闭环。
这些智能体通过一个中央调度器(Orchestrator)进行编排,可以顺序执行,也可以根据情况循环(如SQL验证失败则返回给生成智能体重试)。这种架构的好处是高内聚、低耦合,每个智能体可以独立升级(例如,换用更强的生成模型),也便于问题定位和权限控制。
注意:智能体间的通信数据格式需要严格定义,推荐使用JSON Schema进行约束。例如,意图解析的输出、画像检索的上下文,都应有明确的字段定义,这能极大减少智能体之间的“误解”和错误传递。
3. 关键技术栈与实现细节
纸上谈兵终觉浅,我们来具体看看实现ProSPy这样的框架,需要哪些技术组件,以及如何将它们串联起来。这里我会以一个典型的基于Python的现代数据技术栈为例进行说明。
3.1 数据画像的生成与存储
画像的生成是离线或准实时过程,核心是自动化。
生成工具链:
- 结构获取:使用
SQLAlchemy、psycopg2(PostgreSQL)、pymysql等库的inspect功能,或直接查询INFORMATION_SCHEMA系统表。 - 统计信息获取:对于支持的系统(如PostgreSQL的
pg_statistic),直接查询。更通用的方法是执行一系列分析查询:
对于大数据量表,可以采用采样分析。这里可以结合-- 示例:获取某表某列的基本统计 SELECT COUNT(*) as row_count, COUNT(DISTINCT column_name) as distinct_count, MIN(column_name) as min_val, MAX(column_name) as max_val, AVG(column_name) as avg_val FROM your_table;Pandas或DuckDB进行快速的内存计算。 - 语义信息获取:从数据库注释、维护的数据字典(如存储在某个
meta表中)读取。如果没有,可以尝试用一个小型的NER(命名实体识别)模型对列名进行解析,但这部分精度要求高,实施需谨慎。
画像存储: 生成的画像数据是半结构化的,适合用JSON格式存储。为了支持智能体的高效检索,建议使用向量数据库(如ChromaDB、Weaviate、Qdrant)或支持向量检索的关系型数据库(如PostgreSQL的pgvector扩展)。
- 将每个表、每个字段的描述文本(如:
表名: fact_sales, 描述: 销售事实表, 包含字段: sales_id, order_date, product_id, customer_id, sales_amount, quantity)通过嵌入模型(如text-embedding-3-small)转化为向量。 - 当用户提问“销售额”时,将“销售额”也转化为向量,然后在向量数据库中进行相似度搜索,快速找到
sales_amount字段及其所属表的完整画像。
实现要点:
- 画像需要定期更新,尤其是在表结构或数据分布发生重大变化后。
- 画像生成过程本身要有熔断机制,避免对生产数据库造成过大压力。最好在从库或备份库上进行。
3.2 智能体的具体实现与模型选型
意图解析智能体:
- 轻量级方案:使用规则引擎(如
Rasa框架的NLU组件)或基于spaCy的定制管道。定义一系列意图(如query_ranking,query_trend,query_detail)和实体(如时间,区域,产品),通过模式匹配和少量标注数据进行训练。 - 重量级方案:使用微调过的轻量级LLM,如
Qwen-7B-Chat或Llama-3-8B-Instruct。提供大量“用户问题-解析结构”的配对数据进行指令微调。虽然效果好,但需要训练成本和部署资源。
- 轻量级方案:使用规则引擎(如
SQL生成智能体:
- 模型选择:这是核心,建议投入最好的资源。闭源首选
GPT-4或Claude 3 Opus,它们在复杂逻辑和代码生成上表现优异。开源可选CodeLlama-70B-Instruct、Qwen-72B-Chat或DeepSeek-Coder。较小的模型(如7B、13B)在简单场景下可用,但复杂多表JOIN和嵌套查询上容易出错。 - 提示词工程:这是成败的关键。一个有效的提示词模板应包含:
你是一个资深的{数据库类型}数据库专家。请根据以下数据库结构和业务规则,将用户问题转化为一条准确、高效、安全的SQL查询语句。 # 数据库画像上下文: {此处插入由画像检索智能体整理好的、高度相关的上下文} # 用户问题: {用户原始问题} # 输出要求: 1. 只输出最终的SQL语句,不要有任何解释。 2. 使用清晰的表别名。 3. 包含所有必要的JOIN条件。 4. 如果问题中涉及“最近”,请使用CURRENT_DATE或NOW()函数。 5. 不要使用SELECT *,请明确列出所需字段。 6. 确保WHERE条件中的字段值类型匹配。 SQL: - 温度(Temperature)参数:设置为较低值(如0.1或0.2),以保证生成结果的确定性和一致性,避免每次输出随机的SQL。
- 模型选择:这是核心,建议投入最好的资源。闭源首选
SQL验证与安全智能体:
- 语法检查:使用
sqlparse库进行初步的SQL格式化与解析,或使用对应数据库的驱动尝试cursor.execute(“EXPLAIN …”),如果语法错误会抛出异常。 - 权限与危险操作检查:维护一个黑名单关键字列表(
DROP,DELETE,TRUNCATE,GRANT,ALTER等),并在解析出的SQL语句中检查。更精细的做法是使用SQL解析器(如moz-sql-parser)生成AST(抽象语法树),遍历树节点来识别操作类型和对象。 - 逻辑检查:可以编写一些启发式规则,例如:检查
SELECT语句是否在没有聚合函数的情况下包含了GROUP BY;检查WHERE条件中是否对文本字段使用了数值比较等。
- 语法检查:使用
3.3 框架的编排与API设计
智能体之间需要一个“大脑”来指挥,这就是编排器(Orchestrator)。我们可以用FastAPI或Flask构建一个轻量的Web服务作为总控中心。
核心工作流:
- 接收用户请求(包含自然语言问题)。
- 调用意图解析智能体,得到结构化意图。
- 调用画像检索智能体,根据意图检索相关画像,构建上下文。
- 调用SQL生成智能体,传入意图和上下文,得到初始SQL。
- 调用SQL验证与安全智能体,检查SQL。如果失败,将错误信息反馈给生成智能体进行修正(可设置最多重试次数,如3次)。
- 验证通过后,调用SQL优化与执行智能体,执行SQL并获取结果。
- 调用结果解释智能体,生成自然语言摘要。
- 将SQL、执行结果、自然语言摘要一并返回给用户。
API设计示例:
from fastapi import FastAPI, HTTPException from pydantic import BaseModel app = FastAPI(title="ProSPy Text-to-SQL Service") class QueryRequest(BaseModel): natural_language_query: str db_profile_id: str # 指定使用哪个数据库的画像 max_rows: int = 1000 # 结果行数限制 class QueryResponse(BaseModel): generated_sql: str execution_success: bool execution_time_ms: float | None data: list[dict] | None natural_language_summary: str | None error_message: str | None @app.post("/query", response_model=QueryResponse) async def text_to_sql(request: QueryRequest): # 1. 意图解析 intent = intent_agent.parse(request.natural_language_query) # 2. 画像检索与上下文构建 context = profile_agent.retrieve_and_build(intent, request.db_profile_id) # 3. SQL生成与迭代验证 sql_candidate = None for _ in range(3): # 最多重试3次 sql_candidate = sql_generation_agent.generate(intent, context) validation_result = sql_validation_agent.validate(sql_candidate) if validation_result.is_valid: break else: # 将验证错误作为反馈,融入下一次生成的上下文 context += f"\nPrevious SQL was rejected due to: {validation_result.error}. Please correct it." else: raise HTTPException(status_code=400, detail="Failed to generate a valid SQL after multiple attempts.") # 4. 执行与解释 execution_result = sql_execution_agent.execute(sql_candidate, request.max_rows) summary = explanation_agent.summarize(execution_result.data, intent) return QueryResponse( generated_sql=sql_candidate, execution_success=execution_result.success, execution_time_ms=execution_result.time_ms, data=execution_result.data, natural_language_summary=summary, error_message=execution_result.error )实操心得:在编排器中,一定要为每个智能体的调用设置超时和重试机制。大模型API可能不稳定,网络可能抖动。使用
asyncio和async/await可以提高多个智能体协同工作的效率,尤其是当某些环节(如向量检索)是I/O密集型时。
4. 企业级部署的挑战与应对策略
将ProSPy从原型推进到生产环境,会面临一系列在实验室里遇不到的挑战。这些才是真正体现框架“企业级”成色的地方。
4.1 安全性与权限管控
这是企业的生命线,绝对不能妥协。
查询隔离与沙箱:
- 绝不能使用具有高权限(如
root、sa)的数据库账户来执行生成的SQL。必须为ProSPy框架创建专用的、权限最小化的数据库账户。 - 这个账户的权限应被严格限定:只有
SELECT权限(对于需要写入的场景需额外审批),且只能访问允许业务用户查询的表和视图。 - 理想情况下,可以建立一个查询沙箱:每个用户会话或每次查询,都在一个临时数据库连接或容器内执行,该环境在查询结束后立即销毁,确保无状态和隔离。
- 绝不能使用具有高权限(如
SQL注入防御:
- 尽管SQL是由AI生成的,但仍需防范潜在的提示词注入攻击(用户输入中可能包含试图操纵AI生成恶意SQL的指令)。除了在验证智能体中进行黑名单检查,还应在最终执行前,对SQL进行二次白名单校验。例如,通过SQL解析器提取所有涉及的表名、列名、函数名,与画像中允许访问的元数据进行比对。
数据脱敏与结果过滤:
- 对于包含敏感信息(如手机号、身份证号、邮箱)的字段,即使在SQL中查询出来,在返回给前端前也必须进行脱敏处理(如显示为138****0000)。
- 实现行级数据权限。例如,华东区的销售经理只能看到华东区的数据。这需要在画像中融入用户角色信息,并在SQL生成阶段自动追加对应的
WHERE条件(如AND region_id = ‘EC’)。这通常需要与企业的统一权限中心(如RBAC系统)进行集成。
4.2 性能、稳定性与成本优化
缓存策略:
- SQL结果缓存:对于完全相同的用户查询(经过归一化处理,如去除多余空格、统一大小写),可以缓存其生成的SQL和执行结果。设置合理的TTL(生存时间),例如5分钟,以平衡数据实时性和性能。使用
Redis或Memcached。 - 向量嵌入缓存:对数据库元数据(表名、列名、注释)生成的向量嵌入进行缓存,避免每次检索都重新计算。
- 模型响应缓存:对于常见的、模式固定的查询(如“查询昨天的订单总数”),其对应的AI生成SQL是确定的。可以建立一个小型的“SQL模板缓存”,命中后直接使用,绕过大模型调用,大幅降低成本和延迟。
- SQL结果缓存:对于完全相同的用户查询(经过归一化处理,如去除多余空格、统一大小写),可以缓存其生成的SQL和执行结果。设置合理的TTL(生存时间),例如5分钟,以平衡数据实时性和性能。使用
大模型API的成本与降级:
- 使用GPT-4等高级模型成本不菲。可以设计一个分级调用策略:对于简单、模式清晰的查询,优先使用成本更低、速度更快的模型(如
GPT-3.5-Turbo或开源小模型)。只有当小模型多次生成失败或查询被识别为高度复杂时,才启用GPT-4。 - 监控每个查询的Token消耗和费用,设置每日/每用户的预算上限。
- 使用GPT-4等高级模型成本不菲。可以设计一个分级调用策略:对于简单、模式清晰的查询,优先使用成本更低、速度更快的模型(如
超时与熔断:
- 为每个智能体调用(特别是大模型API调用)设置严格的超时(如10秒)。超时后立即返回友好错误,并可能触发降级逻辑(如返回一个预定义的简单错误SQL提示)。
- 实现熔断器模式(如使用
pybreaker库)。如果某个下游服务(如大模型API或数据库)连续失败多次,则暂时熔断对该服务的调用,直接返回失败,避免系统资源被拖垮。
4.3 可观测性与持续改进
一个黑盒系统是无法被信任的。必须建立全面的监控和反馈闭环。
全链路日志与追踪:
- 为每个用户查询分配唯一的
trace_id,并记录下它在每个智能体环节的输入、输出、耗时和状态。使用结构化日志(JSON格式),便于用ELK(Elasticsearch, Logstash, Kibana)或类似工具进行分析。 - 记录下最终执行的SQL、执行计划、扫描行数、返回行数、执行时间。这些是优化数据库性能和评估AI生成SQL质量的黄金指标。
- 为每个用户查询分配唯一的
人工反馈与模型迭代:
- 提供用户界面,让业务用户在收到查询结果后,可以点击“结果正确”或“结果有误”。对于“有误”的查询,需要人工数据专家介入,分析是意图解析错误、画像信息不全,还是SQL生成逻辑错误。
- 将这些“错误案例”连同正确的修正后的SQL,收集起来形成一个高质量的强化学习数据集。定期用这个数据集对SQL生成模型进行微调(Fine-tuning)或提示词优化,让系统在实践中越用越聪明。
画像健康度监控:
- 监控画像的“新鲜度”。如果某个表的画像超过一周未更新,或检测到该表的DDL发生了变更,则触发告警,提醒管理员更新画像。
- 分析SQL生成失败的原因分布。如果大量失败都源于对某个特定字段的误解,说明该字段的语义画像需要人工修正和增强。
5. 典型问题排查与实战技巧
在实际开发和运维ProSPy这类框架时,你会遇到各种各样稀奇古怪的问题。下面我整理了一些常见“坑”及其排查思路,希望能帮你少走弯路。
5.1 生成的SQL语法正确但结果不对
这是最令人头疼的问题,因为系统没有报错,但给了你一个“安静的错误”。
- 可能原因1:语义歧义未消除。
- 排查:检查意图解析的输出。用户说的“销售额”在业务上可能指“毛销售额”(
gross_sales),而AI可能关联到了“净销售额”(net_sales)字段。这需要丰富画像中的语义信息,或引导用户在提问时更精确(如通过追问智能体:“您指的是毛销售额还是净销售额?”)。
- 排查:检查意图解析的输出。用户说的“销售额”在业务上可能指“毛销售额”(
- 可能原因2:关联路径错误。
- 排查:检查生成的SQL中的
JOIN条件。数据库中存在多条路径可以从A表关联到B表,AI可能选择了不常用或逻辑错误的路径。例如,通过一个已废弃的中间表进行关联。这需要在画像的“关联画像”部分,明确标记出推荐的主关联路径,并赋予更高权重。
- 排查:检查生成的SQL中的
- 可能原因3:过滤条件遗漏或错误。
- 排查:检查
WHERE子句。业务上默认的过滤条件(如只查询状态为“有效”的记录)可能没有被AI捕捉到。需要在给AI的上下文中有显式强调:“请注意,在查询orders表时,通常需要加上WHERE status = ‘active’条件,除非用户特别说明。”
- 排查:检查
- 可能原因4:时区与时间函数处理不当。
- 排查:用户说“今天”,AI可能用的是数据库服务器的
CURDATE(),而业务日期的定义可能是基于另一个时区或另一个字段(如business_date)。必须在画像中明确业务时间字段和时区规则。
- 排查:用户说“今天”,AI可能用的是数据库服务器的
实战技巧:建立一个“问题SQL”回归测试集。将每次发现的错误SQL、对应的用户问题、正确SQL以及错误原因都记录下来。定期用这个测试集跑一遍你的系统,确保修复旧问题的同时没有引入新问题。
5.2 大模型生成速度慢或不稳定
- 优化提示词:冗长、模糊的提示词会增加Token消耗和生成时间。精炼你的提示词,移除不必要的描述。使用“少样本学习”(Few-Shot Learning),在提示词中提供2-3个完美的“用户问题-SQL”示例,这能极大提高生成准确率和速度。
- 调整API参数:除了降低
temperature,还可以尝试设置max_tokens来限制生成长度,避免AI“啰嗦”。对于流式响应,可以评估是否真的需要,非必要情况下关闭流式以更快获得完整响应。 - 实施重试与后备方案:对于OpenAI或Anthropic的API,配置指数退避的重试策略。同时,准备一个后备的、基于规则或模板的简单SQL生成器。当大模型连续失败或超时时,可以优雅地降级到后备方案,返回一个虽然可能不完美但能跑的基础查询,并提示用户“简化您的问题可能获得更佳体验”。
5.3 复杂嵌套查询或窗口函数生成效果差
当前的大模型,即使是GPT-4,在生成非常复杂的多层嵌套子查询或高级窗口函数(如ROW_NUMBER() OVER(PARTITION BY ...))时,也容易出错。
- 策略:分步生成与查询分解:不要指望AI一步到位。当识别到用户问题非常复杂时(如“计算每个部门内销售额排名前五,且连续三个月增长的人员”),可以设计一个子智能体,专门负责“查询分解”。
- 先让AI将复杂问题拆解成几个简单的子问题。
- 为每个子问题生成单独的SQL。
- 最后,再由一个“SQL组装器”将多个子查询的结果,通过临时表或公共表表达式(CTE)组合起来。 这种方法将复杂性控制在了人类更容易理解和调试的范围内。
5.4 向量检索召回不准,导致上下文不相关
如果画像检索智能体提供的上下文牛头不对马嘴,SQL生成智能体再强也没用。
- 优化嵌入模型:通用的文本嵌入模型(如
text-embedding-ada-002)对专业领域术语可能不够敏感。尝试使用在代码或SQL语料上进一步训练过的嵌入模型,或者用你自己的数据库元数据对开源嵌入模型进行微调。 - 优化检索策略:不要只依赖最相似的1个向量。采用多路召回策略:例如,同时检索与用户问题最相似的5个“表描述”向量和10个“字段描述”向量,然后根据一定的规则(如字段必须属于已召回的表)进行融合和去重,形成最终的上下文。
- 引入关键词匹配:在向量检索的同时,并行进行传统的关键词匹配(如BM25)。将两者的结果进行加权融合。有时,“销售额”和
sales_amount的字面匹配比语义相似度更可靠。
构建ProSPy这样的框架,是一个典型的“端到端”系统工程项目,它考验的不仅是你对大模型应用的理解,更是对数据库、软件工程、系统设计的综合能力。从精准的画像开始,通过严谨的智能体分工,再到周密的安全部署和持续的迭代优化,每一步都需要扎实的工程实践。这个过程没有银弹,但每解决一个实际问题,系统的可靠性和价值就增加一分。最终,当业务同事能真正自如地用语言探索数据时,你会觉得这一切的折腾都是值得的。