Skip to content

[Bug] [ChatDashboard] 报告生成阶段发生截断、模板渲染失败及数据库存储溢出问题 #3151

Description

@yuwentao

Search before asking

  • I had searched in the issues and found no similar issues.

Operating system information

Windows

Python version information

=3.11

DB-GPT version

main

Related scenes

  • Chat Data
  • Chat Excel
  • Chat DB
  • Chat Knowledge
  • Model Management
  • Dashboard
  • Plugins

Installation Information

Device information

环境信息
DB-GPT 版本:v0.8.0(源码部署)
Python 版本:3.11.15
操作系统:Windows 11
模型服务:阿里百炼 API(qwen3.7-max-preview、deepseek-v4-flash)
数据库:MSSQL(业务数据)+ MySQL(元数据库)
Skill 名称:自定义业务数据分析技能
问题概述
在使用自定义 Skill 生成包含多维度分析的完整 HTML 报告时(我参考财经的skills,自己定义的html模板,但是报告要输出的内容比较多,需要根据用户的意图输出不同的模块内容,有的模块展示,有的不展示,具体每个模块的内容也是需要图表结合输出来),遇到三个连锁问题:
模型输出长度受限:默认 max_tokens=4096,导致长报告生成不完整,尾部截断。
日志如下:# 日志1:max_tokens 始终为 4096
DEBUG: request.max_new_tokens = 4096
Send request to openai, payload: {'stream': True, 'model': 'deepseek-v4-flash', 'temperature': 0.6, 'max_tokens': 4096}

日志2:template_path 模式渲染失败

The template_path mode returned the raw template without rendering the data,
indicating it's incompatible or requires a different setup.

日志3:降级后生成完整 HTML 但数据库插入失败

(pymysql.err.DataError) (1406, "Data too long for column 'content' at row 1")
'content': '... (62277 characters truncated) ...'
模板渲染失败并强制降级:即使将 max_tokens 增大到 16384 或 32768,template_path 模式仍返回原始模板(占位符未被替换),系统自动降级到 html 参数模式。
数据库存储溢出:模型自动降级(重新输出比较简略的内容),降级模式下生成的完整 HTML 报告内容过大,超出 gpts_messages.content 字段(TEXT 类型)的最大长度,导致插入失败(Data too long for column 'content')。
这三个问题相互关联,最终导致任何包含多模块、长内容的分析报告都无法正常生成和保存。

临时解决
max_new_tokens 来源定位:在 dbgpt/model/proxy/llms/chatgpt.py 的 _build_request 方法中添加 Debug 日志后确认,request.max_new_tokens 的值为 4096 是由上游调用链路传入的,而非该方法的默认值。
修改 dbgpt/model/proxy/llms/chatgpt.py 中 _build_request 方法,将 max_tokens 强制设为不小于 32768:
if request.max_new_tokens:
payload["max_tokens"] = max(request.max_new_tokens, 32768)
else:
payload["max_tokens"] = 32768
手动升级数据库字段类型:ALTER TABLE gpts_messages MODIFY COLUMN content LONGTEXT;

在定位到源码之前,已尝试以下所有常规配置方式,均未生效:在 .env 全局配置文件中设置环境变量:
在 DB-GPT 的 .env 文件中(idea里面输入配置里面设置的环境变量)添加 MAX_TOKENS=16384,重启服务后 request.max_new_tokens 仍为 4096,说明框架当前不读取 MAX_TOKENS 这个环境变量。
将 payload["max_tokens"] 改为 max(request.max_new_tokens, 32768) 后,日志显示上游仍传 4096,但实际 payload 已被覆盖为 32768

在 App 配置的"高级参数"中覆盖:
Web UI 中找不到"高级参数"入口。经排查,因为模型类型为 proxy/openai,前端将部分参数字段设置为只读,无法直接编辑模型参数来覆盖默认值。

dbgpt.model.proxy.llms.chatgpt | Send request to openai,

payload: {'stream': True, 'model': 'qwen3.7-max-2026-06-08', 'temperature': 0.6, 'max_tokens': 4096}

============================================

[[models.llms]]
name = "qwen3.7-plus-2026-05-26"
provider = "proxy/tongyi"
api_key = "${env:OPENAI_API_KEY}"
max_new_tokens = 16384
temperature = 0.0
top_p = 0.1
stream = true
timeout = 300

Models information

============================================

内置应用全局默认参数

生效:首页对话/Skill、知识库、无专属配置的内置功能

不生效:AWEL工作流、自定义代码、有专属配置的应用

dbgpt.model.proxy.llms.chatgpt | Send request to openai,

payload: {'stream': True, 'model': 'qwen3.7-max-2026-06-08', 'temperature': 0.6, 'max_tokens': 4096}

============================================

[app]
temperature = 0.0
max_new_tokens = 8192
top_p = 0.1

stop = ["\n\n说明:", "\n\n解析:", "\n\n补充:", "\n\n注意:", "\n\n以上是", "\n\n总结:"]

============================================

【原生数据库聊天页】专属配置(优先级高于全局app)

仅对平台自带的 Chat with DB 页面生效

不生效:AWEL自定义工作流、自定义代码调用

底层发往模型接口时,max_new_tokens 会转为 payload 中的 max_tokens

============================================

[app.chat_with_db_qa]
max_new_tokens = 16384
temperature = 0.0
enable_sql_check = true
schema_retrieve_top_k = 50

Model Configurations

[models]
[[models.llms]]
name = "qwen3.6-35b-a3b"
provider = "proxy/openai"
api_base = "http://192.168.100.102:9002/v1"
api_key = ""
model = "qwen3.6-35b-a3b"
max_new_tokens = 16384
temperature = 0.0
top_p = 0.1
stream = true
timeout = 300

---- 阿里云百炼:千问3.6系列(当前主力)----

[[models.llms]]
name = "qwen3.6-plus-2026-04-02" # 使用稳定快照
provider = "proxy/tongyi"
api_key = "${env:OPENAI_API_KEY}"

[[models.llms]]
name = "qwen3.6-plus"
provider = "proxy/tongyi"
api_key = "${env:OPENAI_API_KEY}"

---- 阿里云百炼:千问3.6旗舰预览版(可选,Agent最强)----

[[models.llms]]
name = "qwen3.7-max-2026-06-08"
provider = "proxy/tongyi"
api_key = "${env:OPENAI_API_KEY}"

[[models.llms]]
name = "qwen3.5-ocr"
provider = "proxy/tongyi"
api_key = "${env:OPENAI_API_KEY}"

[[models.llms]]
name = "qwen3.7-max-2026-05-20"
provider = "proxy/tongyi"
api_key = "${env:OPENAI_API_KEY}"

模型最大输出Token数(模型级兜底,所有调用该模型的场景均生效)

解决Skill生成HTML报告时内容截断问题,原默认值4096

max_new_tokens = 16384

生成温度,数据分析场景设为0,保证结果严谨稳定,原默认值0.6

temperature = 0.0

核采样阈值,降低输出随机性,配合低温使用

top_p = 0.1

流式输出开关,保持开启保证前端逐字展示

stream = true

请求超时时间,长报告生成耗时更长,避免超时中断300 秒(5 分钟)

timeout = 300

[[models.llms]]
name = "qwen3.6-27b"
provider = "proxy/tongyi"
api_key = "${env:OPENAI_API_KEY}"

[[models.llms]]
name = "deepseek-v4-flash"
provider = "proxy/tongyi"
api_key = "${env:OPENAI_API_KEY}"

[[models.llms]]
name = "glm-5.2"
provider = "proxy/tongyi"
api_key = "${env:OPENAI_API_KEY}"

[[models.llms]]
name = "kimi-k2.6"
provider = "proxy/tongyi"
api_key = "${env:OPENAI_API_KEY}"

[[models.llms]]
name = "qwen3.6-flash-2026-04-16"
provider = "proxy/tongyi"
api_key = "${env:OPENAI_API_KEY}"

[[models.llms]]
name = "qwen3.7-max-preview"
provider = "proxy/tongyi"
api_key = "${env:OPENAI_API_KEY}"

[[models.llms]]
name = "qwen3.5-plus-2026-04-20"
provider = "proxy/tongyi"
api_key = "${env:OPENAI_API_KEY}"

[[models.llms]]
name = "gui-plus-2026-02-26"
provider = "proxy/tongyi"
api_key = "${env:OPENAI_API_KEY}"

============================================

dbgpt.model.proxy.llms.chatgpt | Send request to openai,

payload: {'stream': True, 'model': 'qwen3.7-max-2026-06-08', 'temperature': 0.6, 'max_tokens': 4096}

============================================

[[models.llms]]
name = "qwen3.7-plus-2026-05-26"
provider = "proxy/tongyi"
api_key = "${env:OPENAI_API_KEY}"
max_new_tokens = 16384
temperature = 0.0
top_p = 0.1
stream = true
timeout = 300

[[models.llms]]
name = "qwen3.7-plus"
provider = "proxy/tongyi"
api_key = "${env:OPENAI_API_KEY}"

[[models.llms]]
name = "qwen3.5-omni-plus"
provider = "proxy/tongyi"
api_key = "${env:OPENAI_API_KEY}"

---- 阿里云百炼:千问轻量(可选,高频任务)----

[[models.llms]]
name = "qwen3.6-flash"
provider = "proxy/tongyi"
api_key = "${env:OPENAI_API_KEY}"

---- 阿里云百炼:DeepSeek旗舰(可选,强推理)----

[[models.llms]]
name = "deepseek-v4-pro"
provider = "proxy/openai"
api_base = "https://dashscope.aliyuncs.com/compatible-mode/v1"
api_key = "${env:OPENAI_API_KEY}"

Qwen3.6-35B-A3B

[[models.llms]]

name = "qwen3.6-35b-a3b"

provider = "proxy/tongyi"

api_key = "${env:OPENAI_API_KEY}"

阿里云百炼:的 GLM-5.1

[[models.llms]]
name = "glm-5.1"
provider = "proxy/tongyi"
api_key = "${env:OPENAI_API_KEY}"

阿里云百炼:的 Kimi-K2.5 → Kimi-K2.6

[[models.llms]]
name = "kimi-k2.6"
provider = "proxy/tongyi"
api_key = "${env:OPENAI_API_KEY}"

---- 硅基流动:Kimi-K2.5 视觉Agent(可选,多模态任务)----

[[models.llms]]

name = "Pro/moonshotai/Kimi-K2.5"

provider = "proxy/siliconflow"

api_key = "${env:SILICONFLOW_API_KEY}"

============================================

代码 / SQL 专用模型(至少保留一个)

============================================

---- 阿里云百炼:千问 Coder Plus(推荐,高精度SQL生成)----

#[[models.llms]]
#name = "qwen3-coder-plus"
#provider = "proxy/tongyi"
#api_key = "${env:OPENAI_API_KEY}"

---- 硅基流动:千问开源最强 Coder(可选,复杂SQL备选)----

#[[models.llms]]

name = "Qwen/Qwen2.5-Coder-32B-Instruct"

#name = "Qwen/Qwen3-Coder-30B-A3B-Instruct"
#provider = "proxy/siliconflow"
#api_key = "${env:SILICONFLOW_API_KEY}"

#[[models.embeddings]]
#name = "BAAI/bge-m3"
#provider = "proxy/siliconflow"
#api_key = "${env:SILICONFLOW_API_KEY}"

本地模型

name = "text2vec-large-chinese"

#provider = "hf"
#path = "/app/models/text2vec-large-chinese"
[[models.embeddings]]
name = "text-embedding-v4"
provider = "proxy/openai"
api_base = "https://dashscope.aliyuncs.com/compatible-mode/v1" # 只写基础路径
api_key = "${env:OPENAI_API_KEY}"

[[models.embeddings]]
name = "qwen3.7-text-embedding"
provider = "proxy/openai"
api_base = "https://dashscope.aliyuncs.com/compatible-mode/v1" # 只写基础路径
api_key = "${env:OPENAI_API_KEY}"
#[[models.rerankers]]
#name = "BAAI/bge-reranker-v2-m3"
#provider = "proxy/siliconflow"
#api_key = "${env:SILICONFLOW_API_KEY}"

[[models.rerankers]]
name = "Qwen/Qwen3-Reranker-8B"
provider = "proxy/siliconflow"
api_key = "${env:SILICONFLOW_API_KEY}"

What happened

更改配置文件不生效,不知道是否是不支持这个配置?
另外就是html模板是否还有好的办法,目前是靠模块生成一部分完整的html嵌入进去。

What you expected to happen

期望行为
本 Skill 使用的 HTML 模板和 CSS 样式较为完整,报告包含 4-5 个必选模块和多个按需激活的深度分析模块,以及纯 HTML/CSS 图表,因此单次生成的 HTML 文档体积较大(通常超过 60K 字符)。
模型能够生成足够长的输出(≥ 16384 tokens),完成包含所有分析模块和图表代码的完整 HTML 文档。
template_path 模式能够正常渲染 Jinja2 模板,将数据正确填充到 {{变量}} 占位符。
生成的完整 HTML 报告能够成功写入 gpts_messages 表。
最终在右侧面板展示完整、无截断的分析报告。

How to reproduce

部分内容截取参考:### 5. 渲染报告

  • 时间获取:在渲染报告之前,必须先使用 sql_query 工具执行以下 SQL 查询获取数据库当前时间,并将返回的 report_date 字段值(格式 YYYY-MM-DD HH:MM)直接填入 REPORT_DATE。禁止使用任何模板变量、系统命令或自己猜测时间。
      SELECT CONVERT(VARCHAR(16), GETDATE(), 120) AS report_date;
  • 模板说明:templates/report_template.html 是报告的 HTML 模板。必选模块(Report Overview, Raw Data Display, Data analysis results, Data Insights and Comprehensive Assessment)的标题和卡片容器已在模板中固定,你只需在 data 中填充对应卡片内部的内容(纯文本或简单 HTML)。按需激活的深度分析模块(Trade Scale and Growth, Trade Structure and Balance, Transportation Methods and Major Ports, Trade Methods and Entities, Customs Performance and Trade Facilitation)不在模板中提供标题和容器,你需要自行生成完整的模块 HTML(包括 <h2> 标题和<div class="section-card">容器及其内部全部内容),然后传入对应的变量。未激活的模块传入空字符串 ""。
  • 调用 html_interpreter,使用 template_path 模式:
    {
         "template_path": "user/{{skill_name}}/templates/report_template.html",
         "data": {
         "REPORT_DATE": "此处填入上述 SQL 查询返回的时间字符串,格式 YYYY-MM-DD HH:MM",
         "REPORT_ID": "{{ uuid4() }}",
         "OVERVIEW": "此处填写报告概览卡片内部的纯文本或HTML内容",
         "RAW_DATA": "此处填写原始数据展示卡片内部的纯文本或HTML内容(含表格和导出按钮)",
         "ANALYSIS_RESULTS": "此处填写数据分析结果卡片内部的纯文本或HTML内容",
         "TRADE_SCALE_ANALYSIS": "如果模块激活,填写完整的模块HTML(包括<h2>标题和<div class='section-card'>容器);否则传入空字符串",
         "TRADE_STRUCTURE_ANALYSIS": "如果模块激活,填写完整的模块HTML;否则传入空字符串",
         "TRANSPORT_OFFICE_ANALYSIS": "如果模块激活,填写完整的模块HTML;否则传入空字符串",
         "TRADE_MODE_ANALYSIS": "如果模块激活,填写完整的模块HTML;否则传入空字符串",
         "PERFORMANCE_ANALYSIS": "如果模块激活,填写完整的模块HTML;否则传入空字符串",
         "INSIGHTS_AND_ASSESSMENT": "此处填写数据洞察与综合评估卡片内部的纯文本或HTML内容"
           },
        "title": "East African Customs Data Analysis Report"
    }
  • 重要
    • 必选模块(OVERVIEW, RAW_DATA, ANALYSIS_RESULTS, INSIGHTS_AND_ASSESSMENT)只需提供卡片内部的内容,模板会自动添加标题和容器。
    • 可选模块(TRADE_SCALE_ANALYSIS 等)需要自行生成完整的模块 HTML(包含标题

      和卡片容器
      ),这样模块激活时就直接作为整体插入到报告中。

    • 图表变量如果生成成功,填写图片路径;如果失败或未生成,设为空字符串。
    • 绝对不要在 data 中包含原始数据数组,否则 JSON 过大会导致截断。
    • 如果某个模块未被激活,将对应变量值设为空字符串 ""。

6. 完成

  • 调用 terminate 返回 1-2 句话的简短摘要,概括本次分析的核心结论。
  • 报告会以卡片形式展示在左侧面板,用户点击卡片即可在右侧面板查看完整报告。

Additional context

更改配置文件不生效,不知道是否是不支持这个配置?
另外就是html模板是否还有好的办法,目前是靠模块生成一部分完整的html嵌入进去。

Are you willing to submit PR?

  • Yes I am willing to submit a PR!

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions