- 人工智能
- AI 技能
- 3D渲染
【免费下载链接】img2threejs
Rebuild the object in a reference image as a code-only, procedural, quality-gated, animation-ready Three.js model. Token-efficient image-to-3D.
本文档基于 docs/specs/vocabulary/README.md 展开,系统讲解 img2threejs 项目中"规范化规格词汇表(Normalized spec-record vocabulary)"的数据契约:如何以 JSONL 文件承载经过评审、可提交入库的规格记录,每条记录如何被校验、摄取、分词并进入本地 BM25 检索。读者学完后,将能够理解该目录下所有.jsonl记录的字段语义与稳定类型约束,掌握load_jsonl_records校验入口的错误行为,并能写出符合契约、可被 forge/stage1_intake/search_specs.py 检索命中的合格记录。
一、词汇表在 img2threejs 中的作用
img2threejs 的核心目标是把参考图中的物体重建为"纯代码、程序化、质量门控、可动画"的 Three.js 模型,并强调 Token 高效。在推理阶段,模型需要把一张参考图分解为组件、材质、约束、测量值等结构化知识;这些知识如果每次都由大模型现场"记忆",既消耗 Token 又不稳定。本目录正是为此服务的**本地规格检索(local specification search)**语料库:
- 目录中存放的是**已评审、已提交(reviewed, committed)**的 JSONL 记录,每一条都是一个经过蒸馏的、带溯源的规格陈述;
- 每个非空行恰好是一个 UTF-8 JSON 对象(
docs/specs/vocabulary/README.md第 3-6 行); - 一个集合(collection)可以暂时没有记录文件,但只要记录文件存在,其每一行都必须满足本契约。
从仓库现状看,该目录下已有四个经过评审的语料文件:core_3d.jsonl、core_3d_reconstruction.jsonl、cs2.jsonl、cs2_reconstruction.jsonl,分别覆盖通用 3D 规格词汇与 CS2 武器/材质专项词汇。
二、记录文件的基本格式契约
词汇表目录的格式约束极为严格,任何提交的记录都必须遵守:
- 文件为 UTF-8 编码的JSONL(每行一个 JSON 对象);
- 空行允许存在并被忽略,但非空行必须整体是一个合法的 JSON 对象;
- 不允许出现"半行"或跨行的 JSON 对象;
- 一旦存在记录文件,其所有行都必须通过字段级校验(详见下文"必填字段"),不存在豁免。
对应的读取与校验入口在 forge/_shared/spec_search.py 中已经落地实现(README 中称为"未来接入点",当前仓库已完成):
load_jsonl_records(path: Path)(forge/_shared/spec_search.py#L684-L698):逐行读取 UTF-8 文件,跳过空白行,对每一行执行json.loads与_parse_record字段校验;- 任何失败都会抛出
SpecRecordValidationError(forge/_shared/spec_search.py#L341-L348),该异常的字符串形式为{path}:{line_number}: {reason},即文件路径 + 从 1 开始的行号 + 具体原因; - 契约明确:无效行永远不会被跳过或静默修复("Invalid rows are never skipped or silently repaired")。
测试 forge/tests/test_search_specs.py#L345-L352 专门验证了这一行为:向 fixture 追加一行残缺 JSON{"record_id":后,读取会抛出形如broken.jsonl:2: invalid JSON object的命名错误,而不是悄悄丢弃该行。
三、规范行(Canonical Row)逐字段解读
README 给出了完整的规范示例行(来自 CS2 武器解剖学的"Karambit 安全环"记录),这是所有记录必须对齐的骨架:
{ "record_id": "cs2.karambit.safety-ring", "collection": "cs2", "domain": "weapon-anatomy", "kind": "component", "entity": "karambit safety ring", "title": "Karambit safety ring / Vòng ngón Karambit", "aliases": ["safety ring", "finger ring", "vòng ngón"], "content": "A retention ring at the Karambit's pommel.", "constraints": ["Preserve the opening as a distinct component."], "measurements": [ {"name": "opening diameter", "value": "source-dependent", "unit": "mm"} ], "source_refs": [ { "path": "docs/cs2/3D_Technical_Mapping.json", "key_path": "karambit.components.safety_ring" }, {"path": "docs/cs2-anatomy/karambit.md", "heading": "Safety ring"} ], "evidence_refs": [ {"kind": "source", "ref": "docs/cs2/3D_Technical_Mapping.json"} ], "observation_status": "observed", "confidence": 0.9, "assumptions": [] }关键语义(README 第 49-54 行):
record_id是稳定、小写、点分隔的标识符,绝不从展示标题派生,且必须在措辞变化时保持稳定;collection选择所属检索集合;domain、kind、entity对记录做分类,但不强制全局统一的分类法(每个领域可用自己的分组习惯);title、aliases、content是可搜索文本;aliases保留作者编写的英/越双语术语,归一化与查询扩展发生在之后的处理阶段(即分词器与别名展开)。
3.1 规范行的源码映射
上述 15 个字段在源码中以 TypedDict 形式固化为SpecRecord(forge/_shared/spec_search.py#L95-L110),校验逻辑_parse_record(forge/_shared/spec_search.py#L656-L681)按固定顺序提取并强类型检查每个字段。字段级校验由_record_string(非空字符串,content例外允许为空)、_record_string_list(字符串数组)、_measurements、_source_refs、_evidence_refs等辅助函数完成,任何一个类型不符都会定位到具体的路径:行号:字段。
四、必填字段与稳定类型表
README 以表格形式给出全部 15 个必填字段的稳定类型与语义,这是编写记录时的第一手参考:
| 字段 | 类型 | 语义 |
|---|---|---|
record_id | 非空字符串 | 集合内稳定且唯一的标识符。 |
collection | 非空字符串 | 拥有该记录的集合键。 |
domain | 非空字符串 | 领域分组,如weapon-anatomy或pbr。 |
kind | 非空字符串 | 记录类别,如component、material或constraint。 |
entity | 非空字符串 | 规范的实体或概念名。 |
title | 非空字符串 | 人类可读的可搜索标题。 |
aliases | 字符串数组 | 零或多个作者编写的同义词,已知时包含双语别名。 |
content | 字符串 | 有来源支撑的简明描述;仅当结构化字段已承载可检索细节时才允许为空。 |
constraints | 字符串数组 | 要求、禁止事项或注意事项。 |
measurements | 对象数组 | 每个对象含非空字符串name与value;可选unit、context为字符串。数值保持为来源原文,而非杜撰数字。 |
source_refs | 非空对象数组 | 蒸馏陈述的出处。每个对象含非空字符串path,可含非空字符串heading和/或key_path。 |
evidence_refs | 对象数组 | 辅助性出处。每个对象含非空字符串kind与ref;可选note为字符串。 |
observation_status | 字符串 | 取值为observed、inferred或unverified三者之一。 |
confidence | 数字 | 闭区间0.0到1.0;表示对蒸馏陈述本身的置信度,而非检索相关性。 |
assumptions | 字符串数组 | 限定该记录的显式假设。 |
4.1 表内约束在源码中的落地
measurements:源码_measurements(forge/_shared/spec_search.py#L606-L621)强制name、value为非空字符串,unit、context若出现则必须是字符串(允许空串)。source_refs:源码_source_refs(forge/_shared/spec_search.py#L624-L636)强制数组非空且每个元素必须有非空path;heading与key_path任选其一或同时出现。evidence_refs:源码_evidence_refs(forge/_shared/spec_search.py#L639-L653)强制kind、ref为非空字符串,note可选。observation_status与confidence:_parse_record中,observation_status必须命中{observed, inferred, unverified}白名单;confidence必须为数字且0 <= confidence <= 1,且布尔值会被显式拒绝(type(confidence) is bool直接报错)。
五、溯源(Provenance)设计:source_refs 与 evidence_refs
README 第 76-80 行强调:记录必须保留原始的源位置。这是词汇表"事实准确"原则的根基:
- 用
heading定位 Markdown 章节; - 用
key_path定位 JSON 位置; - 当一种源格式同时提供两种定位形式时,一个 source reference 可以同时包含两者;
- 所有路径均为仓库相对路径,使用正斜杠(
/); evidence_refs可以指向源文件、外部标识符或评审产物,但不能替代source_refs。
两类引用的分工是:source_refs承载"蒸馏陈述的直接出处",evidence_refs承载"支撑性证据"。在 core_3d.jsonl 中可以看到实际用法:例如core.pbr-roughness记录同时引用grimoire/glossary/3d_vocabulary.md(heading: "Material And PBR")、grimoire/intake/image_analysis.md(heading: "Layer 5 — Materials & surface (PBR)")以及docs/raw/img2threejs-skill-dataset.json(key_path: "categories.material_pbr[1]")三类来源,并在evidence_refs中标注notebooklm-research类型的评审产物引用及其 note。
从源码看,SourceRef与EvidenceRef的运行时形态是冻结数据类SourceReference/EvidenceReference(forge/_shared/spec_search.py#L165-L176),摄取 JSONL 时在_ingest_jsonl(forge/_shared/spec_search.py#L867-L898)中逐条重建,并透传到缓存与检索结果序列化中。
六、观察状态与置信度:如何表达"确定性"
README 第 82-86 行给出了三档观察状态的精确含义,这是整份契约中最需要纪律性的部分:
observed:直接由所引用源或参考产物支持;inferred:有依据的合理解读,必须连同其假设一起保留;unverified:有用的术语或候选主张,但仍需确认。
核心原则是:不要编码未经支持的确定性("Do not encode unsupported certainty")。当证据不足时,正确的做法是降低confidence、选择恰当的状态、并写下限定性的assumptions,而不是虚报为observed。
6.1 真实语料中的实践
在 cs2.jsonl 中可以看到差异化实践:
cs2.karambit.safety-ring记录observation_status: "observed"、confidence: 0.85,因为源文档明确提及该安全环为关键指孔细节;cs2.knife.pommel记录observed、confidence: 0.9,其 measurement 直接来自技术映射(metalness 1.0、roughness 0.35);cs2.wear-float-ranges记录在constraints中写明"将记录的区间视为术语支持,而非对未见物品磨损程度的断言",体现了"陈述与解释分离"的边界意识。
七、源码级实现:从记录文件到可检索索引
7.1 接入点load_jsonl_records
README 规划的"未来接入点"在当前仓库中已完整实现。load_jsonl_records(path: Path)(forge/_shared/spec_search.py#L684-L698)的行为与契约逐条对应:
- 以 UTF-8 读取文件,若文件不可读或编码非法,抛出带
路径:0定位的SpecRecordValidationError; - 逐行枚举(从 1 开始的行号),跳过空白行;
- 单行
json.loads失败 →SpecRecordValidationError(path, line_number, "invalid JSON object"); _parse_record逐字段强类型校验(对象、非空字符串、字符串数组、measurements/source_refs/evidence_refs 嵌套结构、状态白名单、置信度区间);- 返回
list[SpecRecord]。
契约中"错误识别输入路径与从 1 开始的行号""无效行永不跳过"的承诺,正是由上述第 3、4 步的实现保证的。
7.2 后续流水线:摄取 → 分词 → BM25
记录文件只是起点。spec_search模块把三种来源(Markdown、JSON、JSONL)统一摄取为SourceDocument(forge/_shared/spec_search.py#L179-L190),其中 JSONL 记录的title、content、aliases、source_refs、evidence_refs被原样保留。之后:
- 分词器(
tokenize,forge/_shared/spec_search.py#L739-L772)执行 Unicode 归一化(默认 NFKC)、casefold、越南语声调折叠(accent_fold: "vi",如độ同时产生do、nhám同时产生nham),并可选保留标识符与数字(如AK-47、0.05-0.15各成一个 token); - BM25 检索(
build_index/search_index,forge/_shared/spec_search.py#L1011-L1084)以默认k1=1.5、b=0.75构建倒排索引,按(-score, record_id)排序; - 缓存生命周期(
load_or_build_index,forge/_shared/spec_search.py#L1752-L1792)通过 schema/tokenizer/config/source 四类指纹判断缓存命中(hit)或重建(rebuilt,原因可为missing/stale/corrupt/forced),并采用临时文件 +os.replace的原子写入。
从源码结构可以推断,词汇表记录、原始文档与配置文件最终在同一套索引管道中统一检索,这正是"本地规格检索"的完整闭环。
八、集合配置:spec_search_profiles.json
记录属于哪个集合、以哪些原始文档为可选源、缓存写到哪里,由 forge/_shared/spec_search_profiles.json 统一声明。当前仓库内置两个集合:
| 集合键 | optional_source_roots | distilled_records | 缓存路径 |
|---|---|---|---|
cs2 | docs/cs2/、docs/cs2-anatomy/ | docs/specs/vocabulary/cs2.jsonl、cs2_reconstruction.jsonl、core_3d.jsonl、core_3d_reconstruction.jsonl | .cache/spec-search/cs2.json |
core_3d | 无 | docs/specs/vocabulary/core_3d.jsonl、core_3d_reconstruction.jsonl | .cache/spec-search/core_3d.json |
defaults中的全局默认值即前文所述的 tokenizer(NFKC / casefold / vi 声调折叠 / 保留标识符与数字)、aliases(enabled: true,max_expansions: 1)与 BM25(k1: 1.5、b: 0.75)。配置文件本身由load_profiles(forge/_shared/spec_search.py#L489-L556)严格解析,任何字段类型不符或profile_schema_version非法都会抛出ProfileValidationError;缓存路径与源路径均强制为仓库内相对路径,绝对路径或含..的穿越路径会被拒绝(防止索引越界写入)。
九、CLI 实战:搜索已入库的规格记录
仓库提供了命令行检索工具 forge/stage1_intake/search_specs.py,可直接对已评审的词汇表记录做本地 BM25 检索:
# 默认在 cs2 集合中检索(默认 limit=3,snippet-chars=250) python3 forge/stage1_intake/search_specs.py safety ring vòng ngón # 指定集合与输出条数,并输出结构化 JSON python3 forge/stage1_intake/search_specs.py --collection core_3d roughness độ nhám --limit 5 --json # 强制重建索引缓存 python3 forge/stage1_intake/search_specs.py --reindex karambitCLI 行为要点(forge/stage1_intake/search_specs.py#L95-L254):
- 参数:位置参数
query(可多个词,空格拼接)、--collection(默认cs2)、--limit(默认 3)、--snippet-chars(默认 250,最小 5)、--reindex、--json; - 人类可读输出打印
Query / Collection / Index(status+reason+fingerprint),每个匹配项输出record_id、score、source(含heading或key_path定位)与首条 snippet; --json输出稳定结构:{query, collection, index, matches},每个 match 含record_id、file_path、heading、key_path、score、snippets、source_refs、evidence_refs;- 错误以结构化码区分:参数类错误(
empty_query、invalid_limit、invalid_snippet_chars、unknown_collection)退出码 2;配置/源/缓存类错误(profile_failure、source_failure、index_failure、cache_failure)退出码 3; - 无匹配是正常成功(退出码 0、
matches为空数组),错误信息不会泄漏绝对路径(测试 forge/tests/test_search_specs.py#L884-L937 验证了路径穿越场景下既无越界写入、也不在输出中出现 Traceback 或仓库根路径)。
十、测试如何守护契约
forge/tests/test_search_specs.py 是这份契约的"活文档",其中与词汇表直接相关的断言包括:
test_future_jsonl_loader_api_is_documented(L326-L330):直接读取本 README,断言其中必须出现load_jsonl_records(path: Path)与SpecRecordValidationError,保证文档与实现不脱节;test_cs2_record_round_trips_with_bilingual_aliases_and_provenance(L332-L343):规范行写出再读回必须逐字段相等,且双语别名与key_path/heading定位完整保留;test_malformed_jsonl_raises_named_validation_error_instead_of_skipping(L345-L352):残缺行按路径:行号:原因报错;test_reviewed_bilingual_records_are_complete_and_source_backed(L356-L400):core_3d至少 12 条、cs2至少 8 条,record_id全局唯一,所有记录字段集合不得超过契约字段,source_refs非空,且双语别名集合与源路径集合必须覆盖既定清单。
这意味着:如果你向该目录提交一条新记录,测试套件会立即校验它的字段完整性、类型正确性、双语别名与溯源要求——契约不是纸面约定,而是可执行的回归门禁。
十一、编写合格记录的操作清单
结合 README 契约与源码校验逻辑,编写一条可入库的规格记录请按以下清单自检:
- 格式:UTF-8、每行一个 JSON 对象、无尾随解释文字;
record_id:小写、点分隔、集合内唯一、不随标题措辞变化;- 分类:
collection用既有集合键(cs2/core_3d),domain、kind、entity保持领域内一致的分组习惯; - 可搜索文本:
title人类可读,aliases尽量补充已知双语同义词(英语 + 越南语),content必须由来源支撑,仅在结构化字段已承载检索细节时才允许留空; - 溯源:
source_refs非空,路径为仓库相对路径、使用正斜杠,Markdown 用heading、JSON 用key_path定位,两种定位可并存;evidence_refs只作辅助,不能替代source_refs; - 测量值:
measurements的value保留来源原文(如"source-dependent"、"0.05–0.15"),绝不编造数字; - 确定性表达:按证据强度选择
observed/inferred/unverified,confidence落在0.0–1.0闭区间且反映陈述置信度而非检索相关性;不确定时降低置信度、写明assumptions; - 提交前验证:运行 forge/tests/test_search_specs.py 相关用例,或直接调用
load_jsonl_records,确认无SpecRecordValidationError。
十二、小结
本目录的词汇表契约本质上是把"模型推理时需要的事实知识"工程化为可评审、可溯源、可检索、可版本化的数据资产:15 个稳定字段约束结构,source_refs/evidence_refs约束事实出处,observation_status/confidence/assumptions约束确定性边界,而 forge/_shared/spec_search.py 中的严格校验、分词器与 BM25 索引则把这份契约变成可运行的本地规格检索能力。任何一条新增记录,只有同时满足格式、类型、溯源与确定性四层要求,才能进入检索管线,为 img2threejs 的"Token 高效"目标提供可靠的事实底座。
- 人工智能
- AI 技能
- 3D渲染
【免费下载链接】img2threejs
Rebuild the object in a reference image as a code-only, procedural, quality-gated, animation-ready Three.js model. Token-efficient image-to-3D.
相关推荐
把 PC 游戏送进客厅:Sunshine 串流服务器 30 分钟落地手册
把 PC 游戏送进客厅:Sunshine 串流服务器 30 分钟落地手册 Sunshine 是一款免费开源的自托管游戏串流服务器,专门负责把你 PC 上的游戏画
音视频后端Kilo 项目土耳其语本地化:tr.md 翻译词汇表规范与落地实践
Kilo 项目土耳其语本地化:tr.md 翻译词汇表规范与落地实践 本文围绕当前仓库中土耳其语翻译词汇表文档 .opencode/glossary/tr.md
人工智能大模型AI Agent代码智能体工具调用交互助手CLIKilo 丹麦语本地化规范解读:.opencode/glossary/da.md 词汇表与 kilo-i18n 落地实践
Kilo 丹麦语本地化规范解读:.opencode/glossary/da.md 词汇表与 kilo i18n 落地实践 丹麦语(da)是 Kilo 多语言本地
人工智能大模型AI Agent代码智能体工具调用交互助手CLI
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考