
简介智能问数正成为企业数据分析的新范式其核心价值在于将自然语言自动转化为可执行的数据库查询大幅降低业务人员获取数据的技术门槛。实现这一目标通常依赖Text-to-SQL与检索增强生成RAG的混合架构前者负责将问题解析为结构化查询语句后者通过向量检索为非结构化文本提供上下文依据。在上市公司财报分析场景中这类技术面临指标口径统一、时间表达解析、多表关联计算等工程挑战同时也为竞赛项目提供了完整的落地演练场。围绕泰迪杯B题“上市公司财报智能问数助手”本文从数据清洗、指标知识库构建、意图识别、SQL生成到结果校验与RAG问答系统拆解了一套兼顾准确率与可解释性的混合技术方案并分享了评测迭代与答辩准备的关键经验为开发者构建可用的财务问答系统提供了直接参考。 说实话看到2026年泰迪杯这个B题的时候我第一反应是终于不是那种纯算法刷分的题了。连续几年数据挖掘竞赛都往“真实业务落地”靠拢但今年这个“上市公司财报智能问数助手”明显是踩在大模型应用的风口上而且题目本身留的发挥空间极大。我们团队从选题到提交前后断断续续做了将近一个月最后拿到了还不错的成绩。这篇文章把我们的完整方案、踩坑记录和代码思路全部整理出来给后面参赛的朋友一个可直接参考的路线图。先说结论这类题目的核心并不是“做出一个完美的系统”而是让评委看到你对“大模型结构化数据业务知识”这套体系的理解深度。题目给了财报数据需求是让用户用自然语言提问系统自动返回正确结果。这背后的技术栈其实就是这些年最火的那个方向——智能问数也就是业内常说的Text-to-SQL加上检索增强生成RAG的混合体。但真正动手做的时候你会发现坑远比想象中多。1. 赛题分析与总体方案设计1.1 赛题需求拆解从题目描述里挖出隐藏考点先花点时间把题目吃透。B题表面的需求是“让用户用自然语言查询上市公司财报数据”但仔细读题你会发现它其实包含了三个层次的能力要求第一层是基础的查询能力。比如用户问“贵州茅台2023年营业收入是多少”系统要能从财报数据里准确取到对应数字。这一层考验的是结构化数据的查询准确性也是整个系统的主干功能。第二层是分析能力。比如用户问“近三年哪家公司的净利润增长率最高”这已经不是简单的“取数”而是需要系统理解“增长率”这个概念自己完成多表关联、排序、计算。这个层级直接区分了“能用的系统”和“能打比赛的方案”。第三层是解释与交互能力。比如用户追问“为什么这个值比去年下降了”系统需要结合财报附注或者非结构化文本给出解释而不是干巴巴地继续吐数字。这一层考验的是对业务上下文的理解也是大多数参赛队容易忽略的地方。我们当时做了一个判断泰迪杯评委看重的不仅是算法准确率更看重“完成度”和“业务思维的闭环”。所以方案设计上我们把“查询准确率”作为底线把“多轮对话”和“结果可解释性”作为加分项而不是一上来就沉迷于微调模型。1.2 技术路线对比纯大模型、模板匹配与混合架构怎么选确定需求之后紧接着就是技术选型。这个环节我们内部开了两次会讨论了三种主流路线。第一种是纯大模型直接生成答案。思路非常直接把财报数据全部转成文本塞进Prompt让模型直接回答。这个方案在数据量小的时候效果还行但我们手里的数据是上百张表、几万行记录大模型上下文窗口根本塞不下而且数字计算极其容易出错。直接否决。第二种是纯模板匹配。提前定义好几百个问答模板用关键词去套。这个方案稳是稳但覆盖率感人随便换一种问法就废了更别提“同比”“环比”“增长率”这种需要语义理解的问题。作为兜底可以用作为主力方案显然不够。第三种就是我们现在用的混合架构规则引擎做前置路由NL2SQL处理结构化数据查询向量检索RAG负责非结构化文本问答再加上一层结果校验和后处理。说白了这个系统有三个大脑在协作一个负责判断“这个问题要不要查数据库”一个负责“怎么查数据库”还有一个负责“查完之后怎么把话术组织好”。当然纯大模型方案在比赛里成本低、上手快第一版Demo确实也能跑但它完全不可控。我们需要的是在评测集上有稳定输出所以混合架构虽然工程量大但实际效果明显更好。重要提示如果你的目标是快速出一版能演示的系统直接让大模型生成SQL可以但一定要在SQL执行前做至少三道校验语法合法性、表名字段名合法性、查询结果空值兜底。不然后面评测的时候你会被随机性的报错坑到怀疑人生。1.3 系统架构总览四层结构各司其职整体架构分四层我们最终命名为“数—算—问—答”四层体系数据层存储财务事实数据MySQL、财报文本向量库处理PDF/HTML抽取的附注文本、指标字典与同义词映射表。计算层负责SQL模板生成、动态代码执行、指标公式计算比如净利润率的计算可能是从多个字段拼出来的必须在这层做公式注册。语义层也就是“问数大脑”包含意图识别模块、槽位抽取模块、SQL生成模块和RAG检索模块。展示层用户对话界面、结果表格渲染、图表生成、导出功能。分层的核心目的只有一个把“出错的概率”分到不同的盒子里去处理。如果一个模块出错其他模块还能兜底而不是整条链路崩掉。2. 数据准备与指标知识库构建比算法更磨人的环节2.1 财报数据的特点与清洗策略缺失值和口径统一是头号敌人泰迪杯提供的财报数据坦白说质量比真实业务数据干净但仍然有不少麻烦。我们处理下来主要有三类问题。第一类是缺失值。并不是所有公司都会完整披露每一项指标比如一些亏损企业就没有“每股收益”的正数数据还有一些公司新上市早期年份的数据直接为空。我们的策略是分指标处理对计算类指标比如增长率如果基期数据缺失标记为无法计算而不是补0对展示类指标前端统一显示“不适用”。第二类是数据口径不统一。这里的水很深——同一个“净利润”有的报表给的是“归属于母公司股东的净利润”有的是“净利润含少数股东损益”如果直接混着用SQL查出来的结果跟财报原文对不上。我们手动建了一张“指标口径表”记录每个指标对应的标准字段、可接受别名以及是否需要在查询时带条件区分母公司口径。第三类是单位混乱。金额字段有的是元、有的是万元、还有的是亿元。我们写了一个单位归一化函数在清洗阶段把数值统一转成“万元”并在指标字典里记录原始单位回答问题时再做展示层单位换算。经验之谈数据清洗阶段一定要写日志。每条异常数据怎么处理的为什么这么处理都要记录下来。后面写论文的时候这部分能撑起一整个章节而且答辩时评委特别喜欢问这些细节。2.2 指标字典与同义词扩展让机器听懂“人话”的关键财报业务的难点在于用户提问时不会使用统一的标准术语。有人问“营收”有人问“营业收入”还有人问“销售额”甚至有人直接问“赚了多少钱”。这些都需要映射到同一个标准指标上。我们建立了一个三级同义词体系标准指标名例如“营业收入”。常见同义词列表例如“营收”“营业额”“销售收入”“主营收入”。模糊语义映射例如“赚了多少”“收入怎么样”这类不精确表达通过关联规则映射到最可能的指标同时在前端提示用户“您想问的是不是营业收入”。具体实现上我们用了一个轻量级的方案——Jaccard相似度加编辑距离双重匹配同时维护一个手工整理的别名表。很多人觉得这个繁琐但实测下来别名表对准确率的提升太明显了。另外一个容易被忽略的点是时间表达也属于“指标知识库”的一部分比如“去年”“上年同期”“最近一季度”“近三年”这些模糊时间词需要预先定义解析规则转成数据库可查询的年份区间。2.3 向量化文本库让大模型有据可查财报除了结构化表格数据还有大量的非结构化文本比如“公司业务概要”“经营情况讨论与分析”这些章节。我们把这些文本按段落切分做向量化存储用于后续的RAG问答。切分这里有个细节直接按固定长度切分会把语义切断。我们按“章节标题段落”的层次结构切分每个文本块控制在500字以内加上章节上下文信息作为metadata这样检索的时候能准确找到对应内容。向量化模型用的通用中文Embedding模型效果完全可以满足需求。3. 核心模块设计与实现从意图识别到SQL生成3.1 意图识别与槽位抽取先搞清楚用户想干嘛整个系统的第一步是意图识别。我们定义了几种核心意图类型分别是“单指标查询”“多指标对比”“趋势分析”“聚合计算”“财报文本问答”等五种。意图识别的实现没有用太复杂的模型而是采用了“规则轻量分类器”的融合方式。规则部分判断一些强特征词比如出现“增长率”“同比”就往计算类靠出现“公司业务”“简介”就往文本问答靠。分类器部分用的是预训练语言模型的文本分类能力输出一个概率分布。两者结合覆盖了绝大部分问法。之后是槽位抽取。我们需要从用户问题中抽取出三个关键实体公司主体、时间范围、财务指标。这里同样没有用复杂模型而是实体字典匹配为主正则和BERT-NER为辅。以“贵州茅台2023年营收和净利润分别是多少”为例槽位抽取的结果就是公司贵州茅台时间2023指标[营业收入净利润]。如果第一步规则解析失败比如用户问“哪个公司2023年净利润最高”就需要进入复杂查询路由让大模型参与生成。3.2 NL2SQL双向方案模板优先大模型兜底NL2SQL是整个系统的技术核心。我们的方案叫“双向生成”优先走模板生成模板覆盖不了才走大模型生成。模板生成的基本思路是把高频查询类型拆成固定的SQL骨架。比如“查询某公司某年某指标”就是经典的“SELECT 指标 FROM 表 WHERE 公司 AND 年份”。多指标查询就是在指标列表处做扩展。聚合查询则涉及GROUP BY和ORDER BY子句。这套骨架大约写了四十个覆盖了评测集里的大多数基础问题。一旦用户问题带有“对比”“排名”“增长”“最大/最小”这类词模板就撑不住了必须走大模型生成SQL。此时我们的Prompt设计就非常关键了。3.3 大模型生成SQL的Prompt工程把数据库Schema喂明白我们在Prompt里重点放了三类信息数据库表结构和字段说明、指标口径说明、典型查询示例。实测下来这三点缺一不可只给表结构不给口径说明模型会把“归母净利润”和“净利润”混为一谈只给Schema不给示例模型在复杂嵌套SQL上很容易张冠李戴。下面是我们实测效果很稳的Prompt模板你可以直接套用你是一名SQL专家请根据以下数据库结构回答用户的财务数据查询问题。 数据库表结构 - 表名: financial_data - comp_name TEXT (公司名称) - year INTEGER (年份) - report_type TEXT (报表类型balance_sheet利润表/income_statement资产负债表/cash_flow现金流量表) - item_name TEXT (指标名称如营业收入、净利润、资产总计) - item_value REAL (指标数值单位为万元) 指标口径说明 - 净利润默认指归属于母公司所有者的净利润除非用户明确说明含少数股东权益 - 营业收入包含主营业务收入和其他业务收入使用报表中直接给出的值 请根据用户问题生成SQL要求 1. 只能使用上述表结构 2. 条件值用单引号包裹 3. 如果用户问增长率需使用SQL计算(本年值-上年值)/上年值 4. 如果查询结果可能为空请使用LEFT JOIN或适当放宽条件 用户问题{question} 生成SQL注意这里有个关键点我们在Prompt里明确要求生成与指标口径相符的SQL并且把常见业务逻辑如增长率直接写成规则告诉模型大幅减少幻觉SQL。3.4 SQL执行安全与结果校验最后的保护伞大模型生成的SQL不能直接扔给数据库执行这是我们从第一天起就定下的铁律。即使不是恶意注入模型偶尔也会生成语法错误或者逻辑错误的SQL。我们的校验链条是第一道校验是关键词白名单如果SQL里出现了除SELECT之外的增删改关键字直接拒绝执行转入兜底方案。第二道校验是表名与字段名合法性解析SQL语句中的表名字段名逐一对比数据库实际结构不匹配则报错。第三道是执行结果校验如果查询结果为空系统不会直接返回“无数据”而是自动触发一次降级重查把年份范围扩大或把指标换成更宽松的表述再查一次。这个设计救了我们好多次。如果以上三道都过不去最终兜底方案是调用RAG检索财报文本。这意味着用户可能会得到一个“模糊但有用”的答案远好过系统直接抛异常。3.5 RAG问答模块让系统能解释、能总结RAG模块负责处理那些无法写成SQL的问题比如“这家公司的主营业务是什么”“公司经营计划提到的发展方向是什么”。实现路径是先把用户问题向量化在向量库中做相似度检索取回最相关的几个文本块再拼到Prompt里让大模型总结回答。这里有一个非常实用的技巧把结构化查询的结果也注入到RAG的Prompt里。例如用户先问“营收是多少”然后追问“主要靠什么业务”我们就把第一轮查询的结果作为上下文上下文输入给RAG让模型回答得更准确。RAG回答的质量取决于检索内容的质量所以文本切分和metadata设计很重要。我们每个文本块都带了“公司名、年份、章节”三个标签检索时可以按公司名先过滤再做相似度检索很大程度上避免了跨公司的上下文污染。4. 系统实现与效果评测从能跑到好用4.1 开发框架与前端交互实现系统整体采用前后端分离架构。后端用FastAPI提供对话接口、SQL执行接口、图表数据接口前端用Vue3加Element Plus搭建对话界面。为了方便评审观看我们还专门做了一版“系统演示模式”界面上实时展示系统正在生成的SQL语句、查询耗时、命中的模板类型等让评委直观看到系统“思考”的过程。对话界面借鉴了市面主流AI聊天产品的设计左侧是会话历史右侧是对话窗口。用户提问后系统返回的内容分为三部分文字答案、结果表格、可视化图表。文字答案由大模型根据查询结果生成会解释“这个数字是怎么来的”表格展示原始明细数据图表则根据查询类型自动选择柱状图或折线图。图表生成这块我们用了ECharts根据查询结果的数据结构自动判断图表类型单指标多公司用柱状图时间序列数据用折线图占比类用饼图。4.2 评测集构建与三轮迭代调优为了量化系统效果我们手工构建了一套约120题的评测集覆盖基础查询、复杂计算、模糊问法、多轮追问四类。然后按“开发—评测—修复”的循环迭代了三轮。第一轮跑完评测集准确率大概在62%左右。错误主要集中在三个地方同义词识别不准、多指标查询漏项、以及增长率计算口径错误。第二轮我们扩充了同义词表调整了模板对“和”“与”“分别”这类连接词的处理逻辑准确率提升到80%左右。第三轮我们重点修复了时间表达问题比如“去年”的解析在年初和年末语境下会产生歧义改为默认取当前日期的上一年并允许用户修正最终端到端准确率稳定在88%上下。剩下10%的错误主要集中在极端表达上比如“跟去年同期比呢”这种口语化问法在没有上下文的情况下确实容易让系统迷糊。我们干脆在系统里加了“多轮澄清”机制一旦置信度低于阈值系统会主动反问“您是想对比2024年和2025年的净利润吗”实测这个交互设计在答辩展示时非常加分。4.3 评测细节与性能数据系统在纯CPU服务器上运行每次问答的端到端耗时平均约1.8秒其中NL2SQL生成占0.8秒SQL执行占0.2秒回答生成占0.8秒。如果开启多轮记忆和上下文增强耗时约2.5秒对演示场景完全够用。关于评测我们内部还开发了一个“半自动化评测脚本”自动运行一批问题把SQL执行结果和预期结果做比对数值误差在0.01以内视为通过。这个脚本在后来调参时帮了大忙建议每个人都做一个。5. 论文写作与竞赛表达的四个要点5.1 论文结构按“业务理解—数据工程—技术方案—系统实现”展开泰迪杯论文有硬性的结构要求但写法上有讲究。我们的大纲是第一节问题背景与业务理解第二节数据概况与预处理第三节总体技术方案第四节核心算法设计第五节系统实现与效果分析第六节总结与展望。第一节特别重要要展现出对“智能问数”行业的理解。我们写了传统BI工具在自然语言交互上的痛点、大模型为数据分析带来的新可能、以及财报分析场景的特殊性数据准确性要求极高、指标口径复杂。这些内容不需要写得多深但要有。第三节和第四节是重点。建议不要只贴代码和公式要画出关键模块的流程逻辑并对每个设计选择给出“为什么这么做”的论证。例如我们专门写了一个对比实验纯模板方案、纯大模型方案、混合方案的准确率对比数据摆出来评委自然信服。5.2 图表与代码排版赏心悦目是隐形的加分项论文里一定要有系统运行截图而且最好是带数据的真实截图。我们花了两个晚上打磨前端界面统一配色、调整字号确保截图放在论文里是好看的。结果展示部分建议用“问题—SQL—结果—解读”四段式来呈现几个典型case让评委能够直观感受系统的能力边界。代码部分不要求全量贴但核心模块的伪代码和关键函数建议附上。5.3 答辩准备重点准备三个问题答辩时评委大概率会问三件事第一系统如何保证查询结果的准确性第二大模型生成SQL出现错误时怎么处理第三如果换一批财报数据系统需要做哪些适配。这三个问题我们提前准备好了答案并且出人意料的是评委确实只问了这三个。所以准备材料时把“准确性保障”“兜底机制”“可迁移性”讲清楚答辩就稳了大半。6. 常见问题与避坑记录6.1 数据层面的五个隐蔽坑数据质量是第一只拦路虎。我们实际处理时遇到了几个很隐蔽的问题第一个是同一指标在不同年份的值可能出现“非数值”字符比如带星号的“**”不清理会让SQL报错。第二个是公司名称写法不统一比如“贵州茅台”有时候写“贵州茅台酒股份有限公司”匹配时必须做公司名归一化。第三个是指标名里存在空格和全角字符直接用等号匹配会失败。第四个是金额字段的单位在不同表格里不一致这个前面提过一定要在清洗阶段统一。第五个是财报数据里有“上年同期数”这样的冗余列会把查询结果搞乱属于数据设计缺陷需要在建表时做好区分。6.2 工程调试中的三个经典错误工程调试阶段最典型的错误有三个这里单独列一下。第一个错误是时间窗口边界没处理好。用户问“一季度”时有些SQL只查了1月3月的数据但“一季度”在某些语境下是指“2024年第一季度”这样比较时需要统一起始时间。我们后来把时间解析统一到“财政年度报告期”两层结构才解决。第二个错误是多指标查询时的SQL拼接逻辑写错。比如“营收和净利润”如果两个指标在同一个表格里是“行转列”的方式存储那一条SQL就能搞定但如果分布在不同的报表里就必须用UNION或者子查询。我们一开始想当然地都用同一个模板导致很多对不上。第三个错误是前端表格渲染大数据量时卡死。返回几百行数据时直接渲染DOM会很慢后来我们用虚拟滚动优化才解决。这个问题在评测时暴露出一次当时很尴尬好在后面调整过来了。6.3 团队协作与时间管理建议最后聊点跟技术无关但同样重要的事。泰迪杯比赛周期不短我们的建议是前两周集中攻坚核心算法第三周做系统前端和论文初稿最后留三到五天全流程联调。团队内部要尽早确定统一的接口约定不然前后端联调时会非常痛苦。文档协作方面我们所有的实验记录和配置参数都统一放在一个共享文档里每个成员负责记录自己模块的关键决策和踩坑记录。最后整理论文时这些记录帮了大忙很多小细节如果没有当时记下来后期很难回忆起来。还有一点代码一定要每天提交到仓库哪怕是实验性的代码分好分支就行。我们有一次调Prompt调出不错的版本但忘了保存后来改坏了再想恢复浪费了一整天。7. 赛后复盘智能问数赛题的设计逻辑比赛结束后重新回顾整个赛题我越来越觉得B题的出题人确实动了心思。财报智能问数这个场景的难度相对适中但覆盖的技术点非常全面既有数据库和SQL的基础也有自然语言处理和向量检索的内容还有大模型应用的工程落地。而且评测按准确率、完成度、创新点综合打分让每个参赛队都有发挥空间。做智能问数系统的时候我一直在想它和传统数据分析工具的本质区别在哪里。做了这个项目之后我的体会是传统工具是“人找数据”用户得知道数据在哪、怎么查、怎么分析而智能问数助手追求的是“数据找人”用户只需要用最自然的方式表达需求剩下的全部由系统解决。这个理念说起来简单实际落地需要数据工程、语义理解、查询生成、结果组织全链路的高度配合。如果明年还有类似赛题我觉得可以进一步把系统扩展成“财务分析智能体”不只是回答“是多少”还能主动生成分析报告比如“发现2024年营收增速放缓主要原因是华南区销售下滑建议关注库存周转”。这个方向再往下深挖可能比单纯做问数更有突破性。根据我们这次的经验参赛的核心竞争力不在于堆砌多少新技术而在于把一个场景做深做透。祝今年的参赛队伍都能取得理想的成绩。本文还有配套的精品资源点击获取