从Qwen-Agent到Nanobot搭建股票ChatBI助手
摘要
本文记录了构建股票 ChatBI 助手的完整实战过程。项目利用 Tushare 采集数据,在 Qwen-Agent 上快速验证了自然语言查询、SQL 工具及 ARIMA、布林带等分析能力。随后,在明确业务边界后,将架构迁移至工程化更强的 Nanobot 框架,并补齐 Gradio Web 界面。核心经验在于遵循“先轻后稳”路线:先用轻量框架验证思路,再进行架构迁移与体验完善。
如何搭建一个股票 ChatBI 助手
写在前面
记录AI Coding 过程及经验分享:从数据收集、数据入库、智能体原型验证,到框架迁移和 Web 界面调试。
理解业务需求,先做轻量级 demo 验证,再做架构迁移与体验完善。
项目目标
股票分析场景下的 ChatBI (Chat Business Intelligence)助手:把数据采集、存储、分析、预测和可视化串在一起,让用户可以直接通过自然语言完成查询和分析。
当前项目围绕以下几只股票做本地验证:
贵州茅台
五粮液
广发证券
中芯国际
目标中的典型能力包括:
历史行情查询:收盘价、成交量、成交额、涨跌幅等
多股票对比:区间涨跌幅、走势对比、统计汇总
自动可视化:根据查询结果自动生成折线图或柱状图
智能预测:基于 ARIMA 预测未来 N 个交易日价格
技术指标分析:使用布林带识别超买、超卖和异常点
当前版本 主要聚焦于本地 SQLite 数据库、历史行情查询、ARIMA、布林带和 Gradio 界面。后续可开发像“实时新闻查询”等能力。
本项目用到的工具与框架
1. nanobot
这个项目最终运行在 nanobot 框架上。它可以理解为一个偏工程化、偏运行时的智能体骨架,一个轻量级的 openclaw 。具备以下特点:
配置驱动,模型、Provider、工具开关都可以放到
config.json运行链路清晰,有
AgentLoop、上下文构建、工具循环这些明确的边界很适合做本地 CLI 型智能体,调试时比黑盒框架更容易定位问题
2. Tushare
股票历史数据来源使用 Tushare获取。
通过
TUSHARE_TOKEN环境变量读取密钥拉取指定股票从
2020-01-01到当天的历史日线数据先保存为
.xlsx再写入本地 SQLite 数据库
这样做的好处是简单、可控、便于复现,也特别适合本地开发和提示词迭代。
3. SQLite
本地验证阶段使用 SQLite。
零部署
易于迁移和备份
查询可控
适合和 Pandas、SQLAlchemy、脚本工具链一起使用
4. Qwen-Agent
Qwen-Agent 的优势是结构相对直接,非常适合快速做一个带工具调用的聊天型助手,且功能完善,提供工程化抽象和开箱即用高级组件。
代码量少,容易看懂
Assistant + tool + WebUI的组合很适合快速试错适合把“自然语言 -> SQL -> 查询结果 -> 可视化”这条链先跑通
在本项目里,Qwen-Agent 更多承担的是 轻量原型框架 的角色。
5. Codex、Trae、Cursor 等 AI 编程工具
AI编程工具是AI开发的核心,或者说是新一代编程的核心,它让人由写代码转化为了读代码,提供思路,框架。但是AI编程的幻觉,针对复杂开发推荐使用TDD模式,本次开发较为简单,由Codex 直接完成。
6. 大模型 API
本项目使用的是阿里云百炼的 Qwen 系列模型,密钥通过环境变量 DASHSCOPE_API_KEY 注入。
为什么先用 Qwen-Agent,再迁移到 Nanobot
很多时候我们一上来就会问:到底该选哪个框架?但真正更有效的问题其实是:
当前阶段我最需要的是“快速验证”,还是“长期扩展”?
对于这个项目:
在原型阶段,我更需要快速验证
在迁移阶段,我更需要更清晰的运行架构
因此路线就自然变成了:

Qwen-Agent 负责“跑通思路”,Nanobot 负责“承接工程化版本”。当然,不止是Nanbot框架,可以根据需要迁移到不同的框架,我们需要提供一个能跑通的demo,让AI学习新框架的用法,在把当前版本代码迁移。
Qwen-Agent 框架

在本项目中的用法
在本项目原型阶段,Qwen-Agent 的角色主要是:
接收用户关于股票查询的自然语言问题
根据提示词理解数据库结构和查询口径
生成 SQL 或调用封装好的工具
自动返回表格和图表
这种方式特别适合早期验证,因为它足够直接,改动反馈也快。
你可以把它理解成一个很适合做“第一版能跑起来 demo”的框架。
Nanobot 架构简介

关键模块理解
config.json
这个文件定义了模型、Provider 和工具开关,是整个项目的配置入口。例如当前项目里最关键的是这几个部分:
当前版本重点依赖本地脚本执行,因此 exec 打开,web 暂时关闭。
AgentLoop
AgentLoop 是整个运行时的核心引擎。它把消息总线、模型、工作目录、工具执行限制、上下文长度和时区等能力统一串起来。
本项目中的核心代码如下:
从这段代码就能看出,Nanobot 比较适合做“边界清楚的智能体系统”。
ContextBuilder
ContextBuilder 类把系统规则、技能说明、当前记忆和环境上下文拼接成模型真正看到的 System Prompt。
本项目里这样实现类似功能,在启动时写入时间上下文:
AgentRunner / LLM + 工具循环
从本质上看,Nanobot 的执行过程依然是“模型判断是否需要工具,再进入工具循环”。
本项目中的 ChatBIHook 把工具调用过程打印出来,方便观察执行过程:
项目具体实现步骤
第一步:用 Tushare 准备数据
让 AI 帮我写出一个数据采集脚本,从 Tushare 拉取四只股票从 2020-01-01 到今天的历史价格,并输出到 Excel 和 SQLite。
这里的思路非常直接:
然后通过 TUSHARE_TOKEN 读取密钥:
最后统一按时间升序排序,写入 Excel 和 SQLite。
这一步很重要,因为后面的所有自然语言查询、预测和可视化,都是建立在数据准备正确的前提上。
第二步:生成建表 SQL,并把数据落入 SQLite
建表语句很简单,但它明确了后续整个项目的数据边界:
对应文件是:
create_stock_daily_price.sql
这张表的设计虽然不复杂,但已经足够支撑当前版本的大部分能力:
历史价格查询
涨跌幅分析
成交量和成交额分析
时间序列建模
布林带计算
第三步:先用 Qwen-Agent 做出“能聊、能查、能画图”的原型
在这个阶段,我并没有急着做复杂架构,而是先做一个轻量级原型,把“自然语言 -> 数据库 -> 结果可视化”跑通。
这一阶段的经验可以概括成一句话:
不要一开始就追求完美架构,先验证交互链路和分析口径。
原型里最重要的并不是代码写得多复杂,而是把下面几件事说清楚:
数据库在哪
表名是什么
用户问“价格”时默认查什么字段
用户问“区间涨跌幅”时如何计算
哪些 SQL 允许执行,哪些绝对不允许
这也是为什么在这类项目中,Prompt 设计的价值非常高。
第四步:不断打磨 SQL 工具的返回结果
早期版本中,我对 SQL 工具做了几轮非常实用的增强:
查询结果只有一行时,不做统计,也不画图
DataFrame 预览不只看前 10 行,而是更综合地展示头尾信息
结果返回中加入描述统计,帮助模型更准确地总结
自动根据数据规模选择折线图或柱状图
横坐标做抽样显示,避免图表标签挤成一团
这些小改动看起来不起眼,但对用户体验和模型最终回答质量影响非常大。
真正让一个查询助手“好用”的,往往不是会不会写 SQL,而是它是否知道:
什么情况该画图
什么情况不该画图
什么情况需要统计摘要
什么情况应该把上下文压缩得更适合模型理解
第五步:补上 ARIMA 预测和布林带分析
在基础查询跑通之后,我继续加入了两个比较典型的分析能力:
ARIMA
当前项目的 ARIMA 技能说明中,约定使用最近一年收盘价,基于 ARIMA(5,1,5) 预测未来 N 个交易日价格。
技能入口命令是:
它适合做趋势性预测验证,但必须明确写清楚:
预测结果仅供学习和分析参考,不构成投资建议。
Bollinger
布林带工具使用的是 20 日周期 + 2σ,用于检测超买和超卖点。
技能入口命令是:
布林带分析很适合做异常点可视化,也能让这个项目从“纯查询助手”进一步扩展为“带技术指标分析能力的助手”。
第六步:从 Qwen-Agent 迁移到 Nanobot
当整个思路在 Qwen-Agent 中被验证得比较清楚之后,我开始把项目迁移到 Nanobot 版本。
迁移的重点不是“把代码原样搬过去”,而是重新梳理运行结构:
配置归拢到
config.json模型 Provider 通过 DashScope 注入
通过技能文件约束不同分析能力的调用方式
利用
AgentLoop承接整个运行时保留 CLI 作为最稳定的调试入口
当前项目主入口是:
agent.py
其中最核心的构造函数是:
这一步让我对整个项目的“运行时结构”有了更强的掌控感。
第七步:补上 Gradio WebUI
最后一步,是把 CLI 助手接到一个更适合演示的 Web 界面上。
当前界面入口在:
webui.py
这个阶段最有意思的,其实不是写 UI 本身,而是调试:
Gradio 5 和 Gradio 6 的参数不兼容
图片本地路径在浏览器端 404
不同 Conda 环境里的依赖版本不一致
Chatbot的消息格式和复制按钮参数在不同版本下不同
最后的解决方案包括:
根据 Gradio 版本动态选择
Chatbot参数将本地生成的图表转为 Base64 内嵌图片,避免
/file=...路由兼容问题保留独立
webui.py,不污染 CLI 入口
这一步其实很能说明一个真实项目的特点:
真正耗时间的,往往不是“写页面”,而是处理不同框架和依赖之间那些看似很小、但很影响体验的兼容细节。
本项目中我比较认可的几个实践
1. 先做本地验证
SQLite、本地图片、本地脚本、本地 CLI,这些选择看起来“朴素”,但非常适合项目初期。
因为在这个阶段,最重要的是减少外部变量,把问题压缩到真正需要思考的地方。
2. 先原型,后迁移
Qwen-Agent 让我快速验证思路,Nanobot 让我把结构理清。这种“先轻后稳”的路线,对个人项目尤其有效。
3. 用技能文件固化分析规则
当前项目里把历史 SQL、ARIMA、布林带分析分别写成技能说明,是一个很实用的做法。这样做的价值在于:
分析口径更清晰
调用命令更明确
更容易约束模型行为
4. 把调试过程当成项目资产
这次 Gradio 的图片问题、版本兼容问题,其实都很典型。如果只是临时修掉,它们很快会再次出现;但如果把这些问题写进复盘,后面就会少踩很多坑。
一些调试心得
这次项目里,我最大的感受不是“写功能有多难”,而是:
真正困难的是在多框架、多依赖、多版本之间,持续把系统保持在一个可验证、可运行、可解释的状态。
有几条经验我觉得特别值得记下来。
1. 先看根因,不要急着补丁式修复
比如图片不显示的问题,最后根因并不是“图没生成”,而是 Gradio 对本地文件路由的处理在当前版本下返回了 404。
如果一开始只盯着前端页面,很容易误判方向。
2. 版本兼容问题永远值得优先确认
Gradio 5 和 Gradio 6 的 Chatbot 参数不同,这类问题如果不先确认版本,后面会浪费很多时间。
3. 调试日志非常重要
像 ChatBIHook 这种打印工具调用参数的设计,在智能体项目里非常有用。因为很多时候,模型“为什么答成这样”,必须结合它实际调了什么工具才能判断。
4. 让项目始终保留一个最稳定的入口
这也是为什么我保留了 CLI。WebUI 可以坏,前端可以兼容出问题,但 CLI 往往是最稳定的诊断入口。
这次项目的局限与后续方向
当前版本已经可以完成:
本地股票历史数据查询
自动图表展示
ARIMA 预测
布林带分析
CLI 交互
Gradio WebUI 交互
但它仍然有很明确的边界:
数据仍然是本地验证数据,不是生产级实时数据流
当前没有真正接入实时新闻查询
Prophet 周期性分析尚未在这版落地
WebUI 更偏演示版,还不是成熟产品化前端
如果后续继续扩展,我最想补的方向会是:
接入实时行情或新闻检索能力
补充 Prophet 或更多时序分析模型
引入更稳定的前端状态管理和历史会话管理
让技能体系进一步模块化,便于横向扩展到更多金融分析场景
结语
这次项目对我来说,最重要的收获不是“又做了一个股票助手”,而是把一条很完整的 AI Coding 路线真正走了一遍:
从业务需求出发
用 Tushare 准备数据
用 SQLite 固定本地验证场景
用 Qwen-Agent 快速做出可交互 demo
用 ARIMA 和布林带补足分析能力
再迁移到 Nanobot,理顺运行架构
最后补上 Gradio,并处理真实调试问题
回头看,这个项目最值得总结的并不是某个单点技术,而是这条方法论:
理解业务需求 -> 打造 skill 或工具能力 -> 用 Qwen-Agent 做轻量级 demo -> 明确边界后做架构迁移。
这条路线很适合个人项目,也很适合 AI 时代的软件原型开发。
如果后面我继续补实时新闻、Prophet、更多股票池、前端产品化体验,这篇文章也会成为一个很好的阶段性起点。
相关文章
暂无相关文章
