news 2026/10/13 2:42:54

openJiuwen DeepSearch 图表数据单位归一化引擎:sub_section_visualization_normalize_units 提示词深度解析

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
openJiuwen DeepSearch 图表数据单位归一化引擎:sub_section_visualization_normalize_units 提示词深度解析
  • 人工智能
  • 大模型
  • AI Agent
  • RAG
  • 深度研究
  • 搜索引擎
  • 后端
  • 代码智能体

【免费下载链接】deepsearch

openJiuwen DeepSearch是一款知识增强的深度搜索与研究框架,有业界领先的片段级引用和溯源推理能力,提供精准Agentic搜索与研究能力

项目地址:https://gitcode.com/openJiuwen/deepsearch
点击查看免费下载

导读

本文深入剖析 openJiuwen DeepSearch 报告中「子小节可视化数据单位归一化」提示词模板 system.md 及其配套 user.md。该提示词是报告生成链路中图表数据从「原始抽取」到「可渲染归一化」的关键一环:它要求 LLM 将来自不同来源、携带不同量纲(如 万、亿、Thousand、Million)的数值记录统一为同一基准单位与全局显示刻度,并输出严格的 JSON。读完本文,你将掌握该提示词的完整规则体系、5 步执行流程、输入输出契约,以及它在 visualization.py 中的实际调用链、服务端 schema 校验与本地快速路径的源码实现。

一、提示词在报告链路中的定位

1.1 两级可视化数据流水线

openJiuwen DeepSearch 的子报告可视化生成遵循「先抽取、再归一化、后渲染」的两级流水线:

  1. 抽取阶段:sub_section_visualization_content提示词从章节原始文本(origin_content)中抽取可制图的结构化数据,输出形如["x_or_category", "value_string", "unit_string"]的三元组记录。此阶段允许保留原始量纲差异(例如 "yuan" 与 "10k yuan"、万辆与万元)。
  2. 归一化阶段:本文主角sub_section_visualization_normalize_units提示词负责把上一步输出中量纲不统一、刻度混杂的记录,统一为同一基准单位 + 单一全局显示刻度,最终输出可直接喂给 Mermaid 生成器的干净 JSON。

这一分工在抽取提示词 sub_section_visualization_content/system.md 中有明确说明:"Simple scale variants of the same base unit are allowed when copied verbatim fromorigin_content, for example 'vehicle' vs '10k vehicles', 'yuan' vs '10k yuan', 'USD' vs 'million USD'. The later normalization step will unify scales."——即抽取阶段刻意保留量纲差异,由归一化阶段统一。

1.2 模板加载机制

与仓库中所有提示词一样,该提示词通过统一的消息构建器加载渲染。在 message_builder.py 中,build_prompt_messages(prompt_name, context)会:

  • 加载prompts/<prompt_name>/system.md作为system消息,并做静态模板树校验(system 模板不允许含运行时变量,见_assert_static_template_tree);
  • 加载prompts/<prompt_name>/user.md,用传入的context变量(通过 Jinja2)渲染为user消息;
  • 若模板缺失或渲染失败,抛出CustomValueException对应的状态码。

提示词契约测试 test_deepresearch_prompt_contracts.py 中登记了该模板的变量契约:"sub_section_visualization_normalize_units": ("language", "records_json"),即调用方只需提供这两个变量。

二、输入输出契约

2.1 输入格式(user.md)

user.md 全文极简,只有一行模板:

Input format: language: {{language}}, records_json: {{records_json}}

两个变量均由调用方注入:

变量类型含义源码默认值
languagestr报告语言,如zh-CN、en-US调用点默认"zh-CN"
records_jsonstr抽取阶段的 JSON 字符串由抽取结果序列化而来

在 visualization.py 中,调用方这样构造上下文:

records_json = json.dumps({"records": extracted_records}, ensure_ascii=False) normalize_context = { "language": visualization_dict.get("language", "zh-CN"), "records_json": records_json, } normalize_input = build_prompt_messages( "sub_section_visualization_normalize_units", normalize_context )

即records_json必须是{"records": [[x_or_category, value_string, unit_string], ...]}结构。

2.2 输出 Schema(固定)

system.md 中定义输出必须是且只能是如下结构:

{ "unit": "string", "records": [ ["category1", 123], ["category2", 456.78] ] }

关键约束:

  • records中每个元素是[x_or_category, 数值]二元组,数值必须是合法的 JSON number(不能是 NaN、Infinity,不能是科学计数法);
  • unit是归一化后的统一单位字符串;
  • 输出只能是纯 JSON,不允许额外文本、空格、换行、注释或 markdown 代码块;
  • 若输入records_json为{}(空对象),直接输出{};
  • 若任何一步校验失败,输出{}(由下游代码决定是否重试)。

这一 schema 与服务端校验函数validate_visualization_normalization_schema严格对应,见下文 5.2 节。

三、角色定义与核心目标

system.md 将模型角色定义为"High-Precision Unit & Scale Normalization Engine"(高精度单位与刻度归一化引擎),并强调是 "a strict, deterministic engine"——即要求模型扮演严格、确定性的处理引擎,而非自由发挥的写作助手。

其核心目标(Core Purpose)分四步:

  1. 解析并校验所有输入值与单位;
  2. 将所有数值转换到共同基准单位(消除 万、亿、Thousand、Million 等刻度差异);
  3. 基于最大绝对值与语言选择一个最优的全局显示刻度;
  4. 输出单位一致、数值已按刻度缩放的干净归一化 JSON。

四、全局规则(Strict Global Rules)

system.md 列出的全局规则是归一化质量的硬约束,逐条展开:

  1. 保留原始顺序与类别:x_or_category及记录顺序不得改动、不得新增、不得删除(对应源码中"record count unchanged (prompt contract)"的强校验,见 5.3 节);
  2. 禁止捏造:不编造数据、不推断缺失值、不给没有单位的记录默认单位;
  3. 数值合法性:所有最终值必须是合法 JSON number(无 NaN、Infinity、科学计数法);
  4. 舍入规则唯一:分数/比率类数值保留 2 位小数,除此之外不允许任何其他舍入;
  5. 输出纯净性:只输出合法 JSON,无多余文本、空格、换行、注释或 markdown;
  6. 失败即空:任何一步校验失败,输出{}。

五、5 步执行流程(Strict Order)

system.md 规定了严格顺序的 5 步执行流程,这是全文的技术核心,逐层拆解如下。

Step 1:解析与校验数值/单位

  • 合法数值形式:纯数字、带千分位逗号的数字(如1,286.6)、分数(a/b)、比率(a:b);
  • value_string 中禁止出现:~、约、≥、>、≤、<、大概以及任何非结构化的附加文本;
  • 单位字符串:trim 后不得为空;允许货币符号(¥、$等);
  • 任一检查失败 → 输出{}。

Step 2:统一基准单位并计算总刻度乘数

这是最核心的一步,system.md 给出统一刻度乘数表:

刻度 token乘数
千 / Thousand1000
万10000
百万 / Million1000000
千万10000000
亿100000000
Billion1000000000
无 / None1

处理流程:

  1. 标准化空白:trim 首尾空格,连续空格合并为一个;
  2. 抽取所有刻度 token:从unit_string中提取全部已定义的刻度 token,支持任意组合(如百万亿、千万亿这类复合刻度);
  3. 累乘:将所有抽取刻度的乘数相乘,得到该记录的总刻度乘数(total scale multiplier);
  4. 剩余部分作基准单位:移除所有刻度 token 后,剩余部分标准化为基准单位;全部记录必须共享同一规范基准单位(拉丁字符忽略大小写);
  5. 标准单位映射:
    • RMB/CNY/¥/人民币/元 → 元
    • USD/US$/$/美元 → USD
    • %/百分比 → %
  6. 任一检查失败 → 输出{}。

Step 3:转换为基准单位数值

  • 基准单位值 = 解析后的数值 × 总刻度乘数;
  • 若任一结果为 NaN/Infinity → 输出{}。

Step 4:选择全局显示刻度与单位

  • 若基准单位是%,直接使用%且不带刻度;
  • 否则按最大绝对值选择显示刻度,且规则随语言不同:
语言阈值区间显示刻度
中文< 10000无
中文10000 ≤ x < 100000000万
中文≥ 100000000亿
英文< 1000None
英文1000 ≤ x < 1000000Thousand
英文1000000 ≤ x < 1000000000Million
英文≥ 1000000000Billion
  • 最终单位格式:
    • 中文:[刻度][基准单位],例如万元、亿元;
    • 英文:[刻度] [基准单位],例如Thousand USD。

Step 5:转换为最终显示值

  • 最终值 = 基准单位值 ÷ 显示刻度乘数;
  • 分数/比率保持恰好 2 位小数;
  • 若任一最终值需要科学计数法表示 → 输出{}。

六、源码级实现证据

6.1 调用链与重试机制

在 visualization.py 中,_normalize_visualization_content是归一化提示词的直接调用方。完整链路为:

_generate_content_for_visualization └─ _process_visualization_task └─ _extract_visualization_data(抽取 + 溯源 + 合规校验) └─ _build_visualization_mermaid └─ _normalize_visualization_content ├─ timeline 特殊处理(直接转 schema) ├─ _normalize_same_unit_records_locally(本地快速路径) └─ build_prompt_messages("sub_section_visualization_normalize_units", ...)(LLM 归一化) └─ _generate_mermaid_code → _precheck_value_variation

归一化调用发生在抽取 schema 校验通过之后。调用时以AgentLlmName.SUB_REPORTER_VISUALIZATION_NORMALIZE(sub_reporter_visualization_normalize,见 node_constants.py)作为 agent 名记录 LLM 统计。

重试逻辑为for j in range(max_attempt_num)(默认max_attempt_num = 3,来自visualization_dict.get("max_attempt_num", 3)):

  1. 调用 LLM 并取content;
  2. 用normalize_json_output清理输出后 strip;
  3. 若结果为"{}"则跳过继续重试;
  4. json.loads失败则记录 warning 后继续;
  5. 通过validate_visualization_normalization_schema校验;
  6. 校验记录条数与抽取记录数一致("Keep record count unchanged (prompt contract)");
  7. 全部通过后组装final_obj(补上image_title与image_type),写入sub_section_visualization_content。

若全部尝试失败,置rs_success=False、error_msg="normalize_failed",下游不再生成 Mermaid。

6.2 本地快速路径:同单位记录不调 LLM

为提高效率与确定性,源码实现了本地快速路径_normalize_same_unit_records_locally(visualization.py):

  • 仅当image_type为bar/line/pie,且所有记录的单位字符串完全一致时启用;
  • 数值解析_parse_visualization_number使用Decimal处理千分位逗号(兼容中英文逗号),拒绝非有限值;
  • 若统一单位以万开头且最大绝对值>= 10000,自动升级为亿并除以 10000 缩放(对应提示词 Step 4 中文阈值规则);
  • 缩放运算_scale_visualization_value同样用Decimal保证精度,能整除则输出int,否则输出float。

例如 test_visualization.py 中的测试用例:输入[["万达电影","647690","万元"], ...]输出{"unit": "亿元", "records": [["万达电影", 64.769], ...]}——这正是"万元→亿元"阈值升级的本地实现。

而test_visualization_normalization_uses_local_same_unit_fast_path(test_visualization.py)验证:当记录同为万辆且最大绝对值< 10000时,直接走本地路径输出unit: "万辆"、数值不做缩放,且LLM 完全不被调用(mocked_llm.assert_not_awaited())。也就是说,只有记录间单位不一致、或本地路径无法处理时,才真正触发本提示词调用 LLM。

6.3 服务端双重 schema 校验

归一化结果在写入可视化内容前,还要经过 report_utils.py 中validate_visualization_normalization_schema的严格校验:

  • unit必须是非空字符串,且不得包含混合单位分隔符(或、/、|、,、;、and,见_has_mixed_unit_separators);
  • 每条记录必须是[str, int|float]二元组,数值必须有限(math.isfinite);
  • 饼图(pie)数值不允许为负;
  • 该函数只接受bar/line/pie三种类型——timeline 在归一化入口被单独转成最终 schema(unit置空,records降为二元组),不进入本提示词。

此外,抽取阶段的validate_visualization_extraction_schema(report_utils.py)在归一化之前就已经阻止了"混合/歧义单位"进入本流程:非 timeline 记录unit_string为空或含混合分隔符即判失败。

6.4 与相邻校验节点的协同

归一化只是可视化质量保障链的一环。在完整流程中,_extract_visualization_data(visualization.py)在归一化之前还会执行:

  • chart_data_traceability_check:校验抽取数据可回溯到原文;
  • chart_compliance_validate:校验图表与章节大纲的相关性/合规性;
  • 任一失败都会把错误信息作为retry_feedback反馈给抽取提示词重试。

归一化完成后,_precheck_value_variation会检查bar/line图数值变异度(去重后数值种类< 3则拒绝渲染,防止"平直无意义"图表),最后才由XYChartMermaidGenerator/PieChartMermaidGenerator/TimelineChartMermaidGenerator生成 Mermaid 代码(见 report_utils.py 中的生成器实现)。

七、实战注意事项与建议

基于 system.md 规则与源码实现,在使用或改造该提示词时需注意以下几点:

  1. language 变量驱动刻度选择:同一组数据在不同语言下会得到不同的显示刻度(万/亿vsThousand/Million),调用方必须正确传入报告语言,否则图表单位可能与读者预期不符。
  2. 复合刻度的乘数逻辑:百万亿、千万亿等复合 token 在 Step 2 中按"所有 token 乘数累乘"处理,设计上覆盖了中文里罕见的复合量纲写法;如遇此类输入,可预期数值会按 100 万亿/1000 万亿 的倍数放大。
  3. 分数与比率保留 2 位小数:只有分数/比率(a/b、a:b)才允许 2 位小数舍入,普通整数/小数不得舍入——这是为了保证条形图/折线图数值不被 LLM 随意"取整美化"。
  4. 失败降级路径明确:归一化失败不会阻塞整个子报告,而是置rs_success=False跳过该图;若某章节数据过于复杂(混合量纲过多),上游抽取阶段就可能已返回{}。
  5. 服务端 schema 是最后防线:不要信任 LLM 输出,validate_visualization_normalization_schema+ 记录数一致性校验(len(normalized_obj.get("records", [])) != len(extracted_records))保证了进入 Mermaid 的数据结构与条数与抽取阶段严格一致。

八、小结

sub_section_visualization_normalize_units是 openJiuwen DeepSearch 报告可视化链路中承上启下的确定性引擎:它接收抽取阶段保留原始量纲的三元组记录,通过"解析校验 → 统一基准单位 → 换算基准值 → 按语言选全局刻度 → 换算显示值"的严格 5 步流程,产出单位统一、刻度最优、结构固定的 JSON。源码中 visualization.py 的同单位本地快速路径、Decimal精度控制、记录数一致性契约与 report_utils.py 的双重 schema 校验,共同保证了图表数据"可追踪、可归一、可渲染";配套测试 test_visualization.py 与提示词契约测试 test_deepresearch_prompt_contracts.py 则为这一契约提供了可回归的工程保障。理解该提示词,即可深入掌握 DeepSearch 报告图表数据从原始文本到 Mermaid 渲染之间的全部量纲处理逻辑。

  • 人工智能
  • 大模型
  • AI Agent
  • RAG
  • 深度研究
  • 搜索引擎
  • 后端
  • 代码智能体

【免费下载链接】deepsearch

openJiuwen DeepSearch是一款知识增强的深度搜索与研究框架,有业界领先的片段级引用和溯源推理能力,提供精准Agentic搜索与研究能力

项目地址:https://gitcode.com/openJiuwen/deepsearch
点击查看免费下载

相关推荐

上一篇:Bilibili视频转文字工具bili2text:模块化架构与工程实践
下一篇:如何快速完整下载电子课本PDF:tchMaterial-parser

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/13 2:42:44

LBM模拟多孔介质自发渗吸:水与空气的孔隙尺度奇妙交互

第一次在计算流体模拟里看到水相前缘像钻迷宫一样穿过随机孔隙、把空气挤成一串串气泡的时候&#xff0c;我意识到格子玻尔兹曼方法&#xff08;LBM&#xff09;下的自发渗吸模拟&#xff0c;远比教材上那张经典的Lucas-Washburn曲线要热闹得多。孔隙喉道里的弯月面一会儿加速突…

作者头像 李华
网站建设 2026/10/13 2:42:15

Upscayl 免费 AI 图像放大:5 分钟出第一张图

Upscayl 免费 AI 图像放大&#xff1a;5 分钟出第一张图 【免费下载链接】upscayl &#x1f199; Upscayl - #1 Free and Open Source AI Image Upscaler for Linux, MacOS and Windows. 项目地址: https://gitcode.com/GitHub_Trending/up/upscayl Upscayl 是一款免费开…

作者头像 李华
网站建设 2026/10/13 2:41:01

本地离线编辑器:Mermaid 本地编辑器从零到可用的完整指南

本地离线编辑器&#xff1a;Mermaid 本地编辑器从零到可用的完整指南 【免费下载链接】mermaid Generation of diagrams like flowcharts or sequence diagrams from text in a similar manner as markdown 项目地址: https://gitcode.com/GitHub_Trending/me/mermaid M…

作者头像 李华
网站建设 2026/10/13 2:40:24

Zerolang std.path 模块实战指南:零分配、纯词法的路径处理 API

【免费下载链接】zerolang The Programming Language for Agents 项目地址&#xff1a; https://gitcode.com/gh_mirrors/zero54/zerolang 点击查看 免费下载 导读 std.path 是 Zerolang 标准库中负责词法&#xff08;lexical&#xff09;路径处理的模块&#xff0c;它不访问…

作者头像 李华
网站建设 2026/10/13 2:39:39

Go电商系统开发实战:订单、库存与幂等性设计要点

把“goshop 电商项目01”这个代号放在标题里时&#xff0c;我其实是想给自己做一份项目存档。这套项目不是网上常见的商品管理 demo&#xff0c;而是一套按真实小商户需求整理的电商系统雏形&#xff1a;前台能浏览商品、加购物车、下单&#xff0c;后台能管理商品、库存和订单…

作者头像 李华