ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

Dify 加 DeepSeek 实现自然语言转 SQL 与自动报表

Dify 加 DeepSeek 实现自然语言转 SQL 与自动报表 简介这份PDF资料面向具备Python与数据库基础的数据分析人员、后端开发者及数据产品经理聚焦如何借助Dify平台与DeepSeek大模型搭建智能数据分析助手解决非技术业务人员难以直接查询数据库、报表生成效率低的问题。资源包共1个PDF文件大小约255KB内容围绕自然语言转SQL、工作流节点设计、数据库连接配置、SQL安全校验、结果统计与图表推荐、Excel与PDF报告导出等环节展开并配有完整Python代码示例、Docker容器化部署方案、数据库初始化脚本及性能缓存优化策略。已有244人学习读者可据此在本地或测试环境复现从自然语言查询到可视化报表输出的全流程理解Dify工作流与DeepSeek模型的集成方式并掌握销售、客户、地域等多场景下的企业级应用思路适合希望降低数据分析门槛、缩短决策周期的团队参考。1. 从一句人话到一张报表Dify 加 DeepSeek 到底在替谁干活业务同事在群里甩来一句“帮我看看上个月华东区退货率最高的五个 SKU”你打开数据库客户端写 CASE WHEN、GROUP BY、ORDER BY再导出 CSV再丢进 Excel 画图四十分钟过去了。这套动作每周重复三次就是这套方案要吃掉的东西。把 Dify 当编排层、DeepSeek 当语义理解与 SQL 生成引擎前端收一句自然语言后端自动完成意图识别、库表定位、SQL 生成、执行取数、图表渲染最后吐回一张可交互报表。适合谁适合手里有 MySQL 或 PostgreSQL、有 Dify 部署经验、想让运营自己查数的数据团队。不适合谁不适合指望零配置开箱即用、也不适合把生产库裸奔给大模型直连的场景。下面按“先跑通最小闭环、再补安全与可视化、最后聊边界”的顺序拆。2. 最小闭环让 DeepSeek 把中文问句翻译成能跑的 SQL2.1 为什么选 Dify 做编排而不是自己写胶水自己写胶水当然可以FastAPI 收请求拼 prompt调 DeepSeek API拿回 SQL连库执行返回 JSON。但这条链路里有一堆脏活——prompt 版本管理、多轮上下文裁剪、失败重试、变量在节点间传递、日志追踪。Dify 的工作流把这些做成了可视化节点改 prompt 不用重新发版调参不用改代码。更关键的是它天然支持把“库表结构”做成知识库检索后再拼进 prompt避免把整张 schema 塞进上下文导致超长报错——这是很多人第一次跑就翻车的地方。选型上DeepSeek 负责两件事一是把自然语言映射到结构化查询意图二是生成方言正确的 SQL。它的强项在中文语义和代码生成对“环比”“同比”“Top N”这类业务黑话理解稳定。Dify 负责把这两步串起来并在中间插入检索、校验、执行三个卡点。2.2 用 Dify 工作流搭出“问句进、SQL 出”的最小链路先建一个 Chatflow 或 Workflow节点顺序如下开始节点收query和db_schema_hint知识库检索节点拿 schemaLLM 节点调 DeepSeek 生成 SQL代码节点做 SQL 白名单校验最后输出。核心是 LLM 节点的 prompt我一般这么写你是 SQL 生成器。根据用户问题和下方表结构只输出一条可执行的 SELECT 语句不要解释不要 markdown 代码块。 表结构 {{#context#}} 用户问题{{#sys.query#}} 约束 1. 只允许 SELECT禁止 INSERT/UPDATE/DELETE/DROP。 2. 时间字段用 order_date格式 YYYY-MM-DD。 3. 金额单位是元不要做汇率换算。这段 prompt 的逻辑说明{{#context#}}是知识库检索注入的 schema 片段{{#sys.query#}}是用户原话。约束里三条分别对应安全、字段歧义、单位歧义是踩坑后加的。参数上DeepSeek 的 temperature 建议设 0.1 到 0.3SQL 生成要的是稳定不是创意max_tokens 给 1024 够用复杂多表关联再往上调。2.3 本地跑通 DeepSeek 调用的最小命令如果你不想一上来就接云端 API本地用 vLLM 起一个 DeepSeek 蒸馏版是常见做法。先确认显卡显存7B 量化版 8G 显存能跑32B 建议 24G 以上。# 启动 vLLM 服务暴露 OpenAI 兼容接口 python -m vllm.entrypoints.openai.api_server \ --model deepseek-ai/deepseek-coder-7b-instruct \ --served-model-name deepseek \ --host 0.0.0.0 \ --port 8000 \ --max-model-len 8192逻辑说明--served-model-name决定 Dify 里填的模型名必须和这里一致。--max-model-len控制上下文窗口设太大显存爆设太小 schema 拼不进去。启动后用 curl 验证curl http://127.0.0.1:8000/v1/chat/completions \ -H Content-Type: application/json \ -d {model:deepseek,messages:[{role:user,content:写一条查询用户总数的SQL}]}返回里有choices[0].message.content就说明通了。然后在 Dify 的模型供应商里选 OpenAI 兼容Base URL 填http://你的IP:8000/v1API Key 随便填一个非空值。注意 Dify 容器访问宿主机要用宿主内网 IP写127.0.0.1会连到容器自己这是新手最常见的连接失败原因。3. 把 SQL 安全地打到数据库连接、校验与执行3.1 数据库连接该配在哪一层Dify 本身不直接连业务库常见做法是在工作流里加一个 HTTP 请求节点调你自己的查询服务或者用代码节点跑 Python 直连。前者更安全后者更快。我一般推荐前者单独写一个只读查询服务用只读账号连库Dify 只负责把 SQL 发过去。只读账号的授权语句CREATE USER bi_reader% IDENTIFIED BY 强密码; GRANT SELECT ON analytics.* TO bi_reader%; FLUSH PRIVILEGES;参数说明只给SELECT不给SHOW DATABASES之外的元数据权限库名限定在analytics。这样即使 SQL 被注入成DROP TABLE数据库层直接拒绝这是最后一道后悔药。3.2 SQL 白名单校验别让大模型自由发挥大模型偶尔会生成DELETE或带子查询的笛卡尔积。在代码节点里做正则校验import re def main(sql: str) - dict: sql sql.strip().rstrip(;) # 只允许 SELECT 开头 if not re.match(r^SELECT\b, sql, re.IGNORECASE): return {ok: False, reason: 非 SELECT 语句} # 禁止危险关键字 forbidden [INSERT, UPDATE, DELETE, DROP, ALTER, TRUNCATE, GRANT] for kw in forbidden: if re.search(rf\b{kw}\b, sql, re.IGNORECASE): return {ok: False, reason: f含禁止关键字 {kw}} # 强制加 LIMIT防止全表扫描拖垮库 if not re.search(r\bLIMIT\b, sql, re.IGNORECASE): sql LIMIT 1000 return {ok: True, sql: sql}逻辑说明先剥分号再查开头再扫关键字最后补 LIMIT。LIMIT 1000是兜底防止“查所有订单”这种问句把生产库拖死。参数上如果你的业务确实需要超过 1000 行把这个值调到 5000 并加超时。校验不通过时把reason回传给用户让他换个问法而不是静默失败。3.3 执行取数并回传结果查询服务收到 SQL 后执行返回列名和行数据。用 Python 的pymysql或psycopg2import pymysql, json def run_query(sql): conn pymysql.connect( hostdb.internal, userbi_reader, password强密码, databaseanalytics, cursorclasspymysql.cursors.DictCursor, connect_timeout5, read_timeout30 ) try: with conn.cursor() as cur: cur.execute(sql) rows cur.fetchall() return {columns: list(rows[0].keys()) if rows else [], rows: rows} finally: conn.close()参数说明connect_timeout5防止连接池耗尽read_timeout30防止慢查询挂死。返回结构里columns单独拎出来是因为后面画图要知道横纵轴字段名。如果rows为空前端要显示“无数据”而不是报错这是体验细节。4. 从结果集到可视化报表字段映射与图表选型4.1 让模型决定画什么图而不是写死拿到columns和rows后再调一次 DeepSeek让它判断该画柱状图、折线图还是饼图。prompt 这么写根据以下查询结果的列名和前三行数据判断最合适的图表类型只输出 JSON {chart: bar|line|pie|table, x: 列名, y: 列名, title: 图表标题} 列名{{columns}} 样例数据{{sample_rows}}逻辑说明x是维度字段y是指标字段。如果模型返回的列名不在columns里代码节点要做一次校验并回退到table。参数上样例数据只给前三行给多了浪费 token 且没必要。4.2 用 ECharts 渲染的最小前端片段前端拿到{chart, x, y, rows}后渲染。以柱状图为例function renderChart(config, rows) { const xData rows.map(r r[config.x]); const yData rows.map(r r[config.y]); const option { title: { text: config.title }, tooltip: { trigger: axis }, xAxis: { type: category, data: xData }, yAxis: { type: value }, series: [{ type: config.chart, data: yData }] }; // chartInstance 是 echarts.init 返回的实例 chartInstance.setOption(option); }逻辑说明xData和yData从行数据里按字段名提取字段名来自上一步模型输出。如果config.chart是pieseries结构要改成[{type:pie, data: rows.map(r({name:r[config.x], value:r[config.y]}))}]。参数上tooltip.trigger设axis适合柱状和折线饼图要设item。4.3 报表缓存与刷新策略同一个问句反复查会浪费模型调用和数据库压力。在查询服务前加一层 Redis 缓存key 用问句的 md5过期时间设 5 分钟。对于“今天实时数据”这类问句缓存要跳过。判断逻辑问句里含“实时”“现在”“今天”就不走缓存。这是业务语义层面的优化比单纯调技术参数管用。5. 避坑与排查那些让工作流跑不通的细节5.1 现象Dify 报 SSL 错误模型调不通原因Dify 容器内访问外部 API 时证书链不完整或者你填的 Base URL 是 https 但本地服务是 http。解决本地服务用 http 就填 http云端 API 报 SSL 错误时检查容器内ca-certificates是否安装必要时在 Dify 的.env里配SSL_VERIFYfalse仅内网测试用生产别关。5.2 现象工作流上下文超长节点报错原因把整库 schema 全塞进 prompt或者多轮对话历史没裁剪。解决schema 走知识库检索只召回相关表对话历史只保留最近 3 轮在 LLM 节点前加一个变量聚合器做裁剪。Dify 的变量聚合器可以把多个变量合并成一个用在这里正好。5.3 现象生成的 SQL 字段名对不上执行报 Unknown column原因知识库里的 schema 没更新或者模型幻觉编了字段。解决schema 知识库设成定时同步每天凌晨重建一次执行失败时把数据库返回的错误信息回灌给模型让它自我修正一次再失败就返回“请换个问法”。5.4 现象Dify 迁移后插件全丢工作流打不开原因插件是本地安装的迁移时只导了应用 DSL没导插件。解决迁移前用dify plugin命令导出插件包或者在新环境重新离线安装。社区版升级时也容易遇到这个问题升级前先备份volumes目录。5.5 现象查询结果中文乱码原因数据库连接字符集没设对。解决连接参数加charsetutf8mb4Dify 代码节点输出时确保 JSON 序列化用ensure_asciiFalse。6. 进阶把“查数”变成“问数”的三个习惯第一个习惯是给模型喂“业务词典”。比如“华东区”对应region IN (上海,江苏,浙江)把这类映射写进知识库模型生成的 SQL 命中率会明显上升。第二个习惯是留“后悔药”每次生成的 SQL 和原始问句都落库出问题时能回溯是哪一步理解偏了。第三个习惯是定期用固定问题集回归测试比如准备 20 个典型问句每次改完 prompt 跑一遍看 SQL 正确率有没有掉。验证方法上我一般用“双人校验”模型生成 SQL 后再用另一个 prompt 让模型自己检查一遍语法和字段是否存在两次都通过才执行。这会多花一次调用但比查错数据强。参数上检查用的 prompt temperature 设 0max_tokens 给 256 就够。这套方案我踩过最大的坑是早期图省事让模型直连生产库结果一次全表扫描把库拖慢被 DBA 追着骂。后来加了只读账号、LIMIT 兜底、超时控制三件套才安稳。如果你也在做类似的事先把安全边界画清楚再谈智能。希望帮到你。本文还有配套的精品资源点击获取
返回列表