BAML jsonish 柔性解析器:把 LLM 自由文本可靠地解析成结构化数据
编程语言AI Agent编译器CLI人工智能【免费下载链接】bamlThe programming language for agents项目地址https://gitcode.com/gh_mirrors/ba/baml点击查看免费下载本文聚焦 BAML 引擎中的jsonish库位于 engine/baml-lib/jsonish围绕其原始文档 README.md 展开它对外暴露的from_str接口保证只要输入里包含符合 schema 的内容就能被灵活地解析出来。读完本文你可以掌握 jsonish 的两段式解析管线JSONish 词法/结构解析 类型强制转换、解析候选与补全状态的数据模型、柔性决策如何被标记与打分以及 BAML 运行时fetch_as、prompt renderer是如何消费其结果的。一、核心接口与设计承诺jsonish 是 BAML 引擎里的一个 Rust cratecrate 名jsonish见 Cargo.toml它解决的核心问题是大模型或其他上游给出的原始字符串往往不是干净的 JSON但业务侧的 schema类型是明确的。原始文档 README.md 将其承诺概括为一个函数pub fn from_str( of: OutputFormatContent, target: FieldType, raw_string: str, allow_partials: bool, ) - ResultBamlValueWithFlags它提供的保证是schema 能从输入中被柔性地解析出来It provides a guarantee that the schema is able to be flexibly parsed out from the input典型场景包括在带前缀/后缀文本里找出目标对象如模型回复The answer is true目标类型是bool按字段名别名alias解析字段把值强制转换cast到正确的目标类型在必要时把单个值包装成数组遵守约束constraints。需要注意源码与文档的演进差异当前 src/lib.rs 中的实际签名为pub fn from_str( of: OutputFormatContent, target: TypeIR, raw_string: str, raw_string_is_done: bool, ) - ResultBamlValueWithFlags即FieldType已由更通用的TypeIR取代而allow_partials语义被反转为raw_string_is_done表示输入是否已完整收到。从调用点 prompt_renderer/mod.rs 可以印证这一对应关系jsonish::from_str(def, target, raw_string, !allow_partials)。第四个参数之所以存在是因为解析器必须支持流式场景——LLM 输出尚未结束时比如只收到[1, 2也要能返回一个部分完成的结构而不是直接报错。返回值BamlValueWithFlags返回类型BamlValueWithFlags定义在 deserializer/types.rs是一棵带解析账本的值树每个节点记录实际解析出的值String/Int/Float/Bool/List/Map/Enum/Class/Null/Media目标类型TypeIRDeserializerConditions即一组柔性转换时打上的Flag详见第四节。它提供了到运行时值体系的多种From转换转BamlValue、转BamlValueWithMeta...并实现score()方法对整棵树打分——分数越小说明解析过程越少动用技巧结果越可信。二、两段式管线JSONish 解析 类型强制转换from_str的实现只有两步见 src/lib.rs第一步jsonish::parse(raw_string, ParseOptions::default(), raw_string_is_done)——把原始字符串解析成一棵与具体 schema 无关的Value树第二步target.coerce(ctx, target, Some(value))——以目标类型TypeIR为驱动把Value树强制转换成BamlValueWithFlags。若目标类型本身就是纯字符串会直接短路返回原始字符串lib.rs因为schema 是 string 时就不该再解析。另外若第二步中出现了Flag::InferedObject(String(...))这类无法接受的标记会显式报错失败——灵活性有边界。2.1 解析入口的四级回退策略第一步的核心是 parser/entry.rs 中的parse_func它按顺序尝试多级策略前一级失败才进入下一级严格 JSON 解析先serde_json::from_str。成功即返回并依据值类型设定补全状态——比如裸数字1会被标记为Incomplete因为模型可能还会继续输出12而带引号的字符串、对象、数组一旦解析成功必然是完整的Markdown 解析allow_markdown_jsonmarkdown_parser.rs 提取 json 代码块若文本里出现多个 JSON 对象会构造一个候选集AnyOf候选包括每个对象单独所有对象作为列表按字符串解析等多种读法全文扫描 JSON 对象all_finding_all_json_objectsmulti_json_parser.rs 在前后缀任意文本中grep 出所有 JSON 片段结果打上Fixes::GreppedForJSON标记修复式解析allow_fixesfixing_parser.rs 处理残缺 JSON缺失括号、未闭合引号等对应Fixes枚举里的修复记录兜底为字符串allow_as_string以上全失败时把整段文本当作字符串候选返回交由第二步的强制转换层去做从文本里抠出 bool/数字之类的工作。每级之间的切换由 parser/mod.rs 的ParseOptions控制默认全开pub struct ParseOptions { all_finding_all_json_objects: bool, // 默认 true allow_markdown_json: bool, // 默认 true allow_fixes: bool, // 默认 true allow_as_string: bool, // 默认 true depth: usize, // 递归深度保护 }next_from_mode会根据当前所处解析模式逐级收窄选项避免重复尝试同一层策略同时parse_func对递归深度设了上限超过 100 层即报 Depth limit reached防止病态输入引发深递归。2.2 Value 树候选集与补全状态解析产物是 jsonish/value.rs 中的Value枚举。除了常规 JSON 值String/Number/Boolean/Null/Object/Array还有三个对柔性至关重要的变体Markdown(String, BoxValue, CompletionState)从 Markdown 代码块里挖出的 JSON附带原文标记FixedJson(BoxValue, VecFixes)经过修复/扫描才得到的 JSONFixes枚举记录了GreppedForJSON全文扫描所得、InferredArray推断出的数组包装等修复动作AnyOf(VecValue, String)多个解析候选。同一段文本可能有多种合理解读对象、列表、字符串jsonish 不急着裁决而是把候选集原样传给第二步让目标类型来选最优。每个带状态的值都携带CompletionStateComplete/Incomplete支撑流式解析completion_state()会自底向上聚合任一候选未完成则整体未完成complete_deeply()可在输出结束后把整棵树标记为完成。顶层裸数字会被刻意标为 Incomplete见 entry.rs因为数字可能被后续 token 延长。三、强制转换层五个柔性场景的落地第二步的实现在 deserializer/coercer/ 目录下按类型分文件组织coerce_alias.rs字段名别名匹配对应文档中 Parsing in field names with aliasescoerce_class.rs / coerce_enum.rs类与枚举的字段/取值匹配coerce_primitive.rs基础类型转换Casting to the right typecoerce_array.rs数组解析与单值包装为数组Wrapping around arrays when necessarycoerce_map.rs / coerce_union.rsmap 与联合类型含打分选择最优分支match_string.rs从自由文本中匹配目标取值。约束Obeying constraints则由 deserialize_flags.rs 中的Flag::ConstraintResults(Vec(String, JinjaExpression, bool))承载——每个约束的求值结果名称、Jinja 表达式、是否通过被记录在解析账本里最终通过constraint_results()汇总给运行时。测试用例直观展示了这些柔性行为摘自 tests/test_basics.rs// 千分位数字直接解析 test_deserializer!(test_number_2, EMPTY_FILE, 12,111, TypeIR::int(), 12111); // 大小写不敏感的布尔 test_deserializer!(test_bool_2, EMPTY_FILE, True, TypeIR::bool(), true); // 前缀文本里抠出 bool并自动包成列表 test_deserializer!( test_bool_wrapped, EMPTY_FILE, The answer is true, TypeIR::bool().as_list(), [true] ); // 带加粗 Markdown 的结论 test_deserializer!( test_bool_wrapped_mismatched_case_preceded_by_text, EMPTY_FILE, The tax return you provided has section for dependents.\n\nAnswer: **True**, TypeIR::bool(), true ); // 歧义输入则明确失败而不是猜 test_failing_deserializer!( test_ambiguous_bool, EMPTY_FILE, The answer is true or false, TypeIR::bool() );这个测试目录还覆盖 别名、类、约束、联合类型、部分值/流式 等主题Cargo.toml 中用 criterion 配置了 字面量、类、列表、联合类型、部分值 等基准说明该库在性能与行为边界上都有系统性验证。四、Flags 与 Score让每一次开恩都留痕柔性解析最危险的副作用是静默地歪曲数据。jsonish 的对策是决策留痕每动用一次技巧就向DeserializerConditions打一个Flag。Flag 枚举 相当详尽能回答这个值是怎么来的例如ObjectFromMarkdown/ObjectFromFixedJson(VecFixes)对象来自 Markdown 代码块或修复后的 JSONImpliedKey(String)/ExtraKey(String, Value)字段名被推断出来或出现了 schema 之外的多余键SubstringMatch/StrippedNonAlphaNumeric值是从文本子串匹配、或剥掉非字母数字字符后得到的SingleToArray单值被包装成了数组StringToBool/StringToFloat/FloatToInt等类型强转记录FirstMatch/UnionMatch联合类型在多个候选中选了第一个/某个分支并保留全部候选的成败结果Incomplete/Pending流式场景下的完成状态标记。基于这层账本库提供两类可观测能力打分score.rs 中的WithScore让每个Flag有代价BamlValueWithFlags::score()递归求和见 types.rs。打分机制使联合类型等场景能从多个候选分支中择优也让上层能判断这个结果干净还是勉强可解释错误explanation_json()types.rs、lib.rs把失败原因按root.field.parsed:0这样的作用域路径组织成 UI 可渲染的 JSONParsingErrorToUiJson供编辑器/Studio 等前端直接展示。五、运行时消费从解析结果到 BAML 值jsonish 的产出最终服务于 BAML 运行时。在 async_vm_runtime.rs 中表达式函数的fetch_as拿到 HTTP 响应体后直接调用jsonish::from_str(output_format, parse_as_type, body, true)把任意响应体按目标类型解析成BamlValueWithFlags再包成ResponseBamlValueprompt_renderer 同理用!allow_partials传入完成标志。ResponseBamlValuelib.rs是面向流式的最终封装元数据ResponseValueMeta携带(flags, checks, completion, TypeIR)。其Serialize实现区分SerializeMode::Final与Partial两种模式——流式输出未完成时序列化会附带state流状态字段且类字段按该字段是否已 required 完成单独决定用 Final 还是 Partial 序列化lib.rs从而让 SDK 用户能在 token 到达的瞬间看到部分但有效的结构化响应。六、工程要点小结两段式架构先得到 schema 无关的Value候选树再由目标类型coerce收敛是 jsonish 能同时服务 LLM 输出、HTTP 响应、prompt 渲染结果等多种来源的原因候选集而非裁决AnyOf把多种合理解读延迟到类型已知时才选择配合Fixes/Flag保证选择过程可追溯、可打分流式一等公民CompletionState与raw_string_is_done参数贯穿解析、转换、序列化三层残缺输入返回部分值而不是抛错跨平台Cargo.toml 为 wasm32 目标单独引入了uuid/getrandom的 js feature说明该库也能编译进 WebAssembly供浏览器端语言客户端使用。如需继续深入建议按 src/lib.rs → parser/entry.rs → coercer/ → tests/ 的顺序阅读源码测试目录基本就是每个柔性能力的活文档。赞分享编程语言AI Agent编译器CLI人工智能【免费下载链接】bamlThe programming language for agents项目地址https://gitcode.com/gh_mirrors/ba/baml点击查看免费下载相关推荐agno 文本抽取Text Extraction用 Pydantic Schema 把自由文本变成结构化数据agno 文本抽取Text Extraction用 Pydantic Schema 把自由文本变成结构化数据 导读 cookbook/data_label人工智能大模型AI AgentAgent 框架多智能体工具调用RAGAgent 工作流Agent 记忆Tokenization 与数据形状全解析train-llm-from-scratch 如何把文本变成可训练张量Tokenization 与数据形状全解析train llm from scratch 如何把文本变成可训练张量 本篇技术指南以仓库文档 docs/found人工智能大模型深度学习预训练微调强化学习rrweb 序列化机制解析如何把 DOM 转成可传输、可回放的数据结构rrweb 序列化机制解析如何把 DOM 转成可传输、可回放的数据结构 导读 本文聚焦 rrweb 序列化Serialization模块的设计与实现为什前端可观测性开发工具上一篇消息队列中的UUID终极指南在Kafka和RabbitMQ中实现全局唯一标识符下一篇OpenCode开源AI编程助手如何让你的开发效率提升3倍创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

相关新闻

TEN Framework 中的 clasp:答案集求解器的工作原理、构建方式与在依赖解析中的落地

TEN Framework 中的 clasp:答案集求解器的工作原理、构建方式与在依赖解析中的落地

人工智能AI Agent多模态语音AI 应用 【免费下载链接】ten-framework Open-source framework for conversational voice AI agents 项目地址: https://gitcode.com/TEN-framework/ten-framework 点击查看 免费下载 本篇以 vendored 在仓库内的 clasp README 为核心&…

2026/9/25 3:00:31 阅读更多 →
Ghost Downloader 3 新手完整指南:一个下载器搞定 HTTP、磁力和 M3U8

Ghost Downloader 3 新手完整指南:一个下载器搞定 HTTP、磁力和 M3U8

Ghost Downloader 3 新手完整指南:一个下载器搞定 HTTP、磁力和 M3U8 【免费下载链接】Ghost-Downloader-3 The only downloader you need. 下载器的集大成者。 项目地址: https://gitcode.com/GitHub_Trending/gh/Ghost-Downloader-3 手上一堆下载需求&…

2026/9/25 2:59:30 阅读更多 →
RisingWave 源码结构导读与 Rust 宏展开调试指南

RisingWave 源码结构导读与 Rust 宏展开调试指南

数据库流处理后端数据工程 【免费下载链接】risingwave Event streaming platform for agentic AI. Continuously ingest, transform, and serve event streams in real time, at scale. 项目地址: https://gitcode.com/gh_mirrors/ri/risingwave 点击查看 免费下载…

2026/9/25 2:59:30 阅读更多 →

最新新闻

Playnite 使用指南:三步把多平台游戏和模拟器合并进一个库

Playnite 使用指南:三步把多平台游戏和模拟器合并进一个库

Playnite 使用指南:三步把多平台游戏和模拟器合并进一个库 【免费下载链接】Playnite Video game library manager with support for wide range of 3rd party libraries and game emulation support, providing one unified interface for your games. 项目地址:…

2026/9/25 3:45:59 阅读更多 →
基于Python的自闭症儿童教育资源分配与个性化教学计划系统

基于Python的自闭症儿童教育资源分配与个性化教学计划系统

做这个系统的念头,最早是我在和一些特殊教育机构的老师聊天时产生的。他们日常面临一个很现实的问题:手里可能有几百条教育资源,但面对每一个特质完全不同的孩子时,根本没法快速判断该给孩子用什么材料、定什么教学计划。有的老师…

2026/9/25 3:45:59 阅读更多 →
论文降AI率工具免费横评:原理、实测与不花一分钱的完整流程

论文降AI率工具免费横评:原理、实测与不花一分钱的完整流程

今年年初,我帮几个研究生改论文初稿,发现一件让人非常头疼的事:查重报告里除了常规的“重复率”,又多了一项“AIGC疑似率”——明明是自己一个字一个字敲出来的论证,却被标成了“疑似AI生成”。更离谱的是,…

2026/9/25 3:45:59 阅读更多 →
魔百盒HG680-LC刷安卓9全网通固件:线刷救砖与去广告实战

魔百盒HG680-LC刷安卓9全网通固件:线刷救砖与去广告实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/9/25 3:45:59 阅读更多 →
24GB显卡跑70B大模型:GPTQ/AWQ/GGUF量化踩坑与TaoToken配置实录

24GB显卡跑70B大模型:GPTQ/AWQ/GGUF量化踩坑与TaoToken配置实录

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/9/25 3:45:59 阅读更多 →
NodeGui 中的 ColorDialogOption 枚举解析:颜色对话框选项的值、组合方式与底层实现

NodeGui 中的 ColorDialogOption 枚举解析:颜色对话框选项的值、组合方式与底层实现

桌面应用跨平台 【免费下载链接】nodegui A library for building cross-platform native desktop applications with Node.js and CSS 🚀. React NodeGui : https://react.nodegui.org and Vue NodeGui: https://vue.nodegui.org 项目地址: https://git…

2026/9/25 3:44:58 阅读更多 →

日新闻

AI元人文:从工具使用到思维重构的深度探索

AI元人文:从工具使用到思维重构的深度探索

最近半年我一直在琢磨一件事:AI元人文到底是什么?说白了,就是“用元视角重新审视人与AI的关系”,也在“探索AI如何反向逼着我们发现自己的思考边界”。标题里的“元探索”,在我看就是一层套一层的追问——当你用AI解决…

2026/9/25 0:00:41 阅读更多 →
Python+CNN车牌识别实战:从数据预处理到模型训练与部署

Python+CNN车牌识别实战:从数据预处理到模型训练与部署

简介:基于Python与卷积神经网络的车牌识别项目,面向计算机视觉初学者及智能交通开发者,目标是帮助用户掌握从数据预处理、模型构建到实际部署的完整流程。压缩包共25个文件,包含jpg/png图像样本、py训练脚本、md说明文档、dat数据…

2026/9/25 0:00:41 阅读更多 →
Vim基础操作全攻略:保存退出、模式切换与高频命令实战

Vim基础操作全攻略:保存退出、模式切换与高频命令实战

1. 项目概述1.1 核心需求解析今天聊聊Vim。写这个题目的原因是:几乎每个后端开发者、运维人员、数据工程师某天都会遇到一个场景——深夜加班,服务器登录界面只有黑底白字,编辑器只有vi/vim,你必须在五分钟内完成一次配置修改并保…

2026/9/25 0:00:41 阅读更多 →

周新闻

Flutter for OpenHarmony游戏卡片渐变背景实战:从原理到性能优化

Flutter for OpenHarmony游戏卡片渐变背景实战:从原理到性能优化

直接铺开项目本身吧。这几个月我一直在折腾一件事:用Flutter给OpenHarmony做一款游戏集合类的App,说白了就是把若干小游戏塞进一个壳里,用统一入口分发。这个方向本身不算新鲜,真正让我花了不少心思的,是首页那堆游戏卡…

2026/9/24 14:34:13 阅读更多 →
Word表格编号全攻略:从列表编号到题注交叉引用

Word表格编号全攻略:从列表编号到题注交叉引用

写Word文档,最让人头疼的往往是那些“看起来不起眼”的小问题。比如表格编号这事:今天在表后面多加了两个空白行,明天给客户交稿前发现整个章节的编号全部错位,光是挨个改序号就能耗掉大半个下午。我前阵子帮人整理一份上百页的技…

2026/9/24 9:10:42 阅读更多 →
从第一个站到第二个站:独立开发者的静态网站选型与落地实践

从第一个站到第二个站:独立开发者的静态网站选型与落地实践

1. 项目概述1.1 核心需求解析做独立开发者这几年,说实话,第一个网站上线的那天晚上我兴奋得没睡着。但等它跑了半年,流量惨淡、功能臃肿、代码自己都懒得看第二遍之后,我才慢慢琢磨明白一个道理:第一个网站是练手&…

2026/9/24 14:33:56 阅读更多 →

月新闻

持续集成 流水线自动化与 声明式交付 实践:原型怎样变成可用功能

持续集成 流水线自动化与 声明式交付 实践:原型怎样变成可用功能

持续集成 流水线自动化与 声明式交付 实践:原型怎样变成可用功能分类:[AI/大模型]细分主题:AI 增强型 CI/CD 流水线自动化与 GitOps 实践:Agent 工作流、工具调用与任务拆解:从原型到生产的验收清单很多团队在尝试用大…

2026/9/24 12:50:34 阅读更多 →
容器编排 生产环境运维与排障实战:复盘记录怎样真正派上用场

容器编排 生产环境运维与排障实战:复盘记录怎样真正派上用场

容器编排 生产环境运维与排障实战:复盘记录怎样真正派上用场分类:[工程技术]细分主题:Kubernetes 生产环境运维与排障实战:可复制的项目复盘模板与决策记录大部分团队的事故复盘报告,最后都变成了躺在 Confluence 或钉…

2026/9/24 14:33:48 阅读更多 →
容器 容器化技术与镜像安全管理:核心链路应该先拆哪一步

容器 容器化技术与镜像安全管理:核心链路应该先拆哪一步

容器 容器化技术与镜像安全管理:核心链路应该先拆哪一步分类:[工程技术]细分主题:Docker 容器化技术与镜像安全管理:核心链路的逐步实现与关键代码取舍面对一个积累了五六年历史包袱的单体架构应用(包含 Web 接口、后台…

2026/9/24 12:49:17 阅读更多 →