尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

Serial-Studio 0012 规格解析:为大型遥测项目打造 LLM 可发现性原语(project.search / project.group.get / 分页列表)

Serial-Studio 0012 规格解析:为大型遥测项目打造 LLM 可发现性原语(project.search / project.group.get / 分页列表) Serial-Studio 0012 规格解析为大型遥测项目打造 LLM 可发现性原语project.search / project.group.get / 分页列表【免费下载链接】Serial-StudioOpen-source telemetry dashboard. Supports UART, BLE, MQTT, Modbus, CAN Bus and more.项目地址: https://gitcode.com/GitHub_Trending/se/Serial-Studio本文基于 Serial-Studio 仓库中已完成的规格 spec 0012 — LLM discoverability primitives for large projects系统讲解当项目膨胀到数百个数据集后应用内 AI 助手为何无法导航项目、Serial-Studio 如何引入project.search、project.group.get、meta.search三个发现型命令并为全量列表命令补齐offset/limit分页以及三种不完整结果截断 / 分页 / 转录老化的自解释机制。读完本文你可以理解这套 API 的设计动机、全部参数与默认值、双 ID 命名陷阱并能结合 集成测试 在本地复现验证。问题起源570 个数据集项目里助手在猜标题规格的前言记录了一次真实会话在一个570 个数据集 / 87 个分组的压力仪表项目上应用内 AI 助手陷入了两个极端之间的死区列全量。project.dataset.list、project.group.list、project.dataset.getExecutionOrder默认返回全部条目。在 570 数据集项目上序列化结果会撑爆每个模型供应商的工具结果字节预算默认约 4 KB被钳制在 2–16 KBfs.*有更大的 48 KB 预算但project.*没有。超尺寸的结果不会被优雅截短——而是被整体替换为一个带truncated:true标记的字节前缀 preview 字符串助手拿到的是第一个分组 JSON 的破碎片段自己请求的结构一个都不剩。且这些命令没有offset/limit可以按页取回。精确解析单条。assistant.dataset.resolve、project.dataset.getByPath、project.dataset.getByTitle都要求精确标题或路径——但助手本来就是因为不知道标题才来找的。结果就是助手开始逐个猜测数据集标题Channel 1、PT-1、烧掉大量工具调用最终不得不请人肉把标题读出来。维护者给修复定下的框架是想想人类面对一本一万页的 PDF 手册会怎么做——用目录和搜索功能。助手需要同样一类的导航原语一个搜索、一个廉价的钻取、可分页的列表外加一份准确的身份模型文档。同一会话还暴露了两个复合痛点一并进入本规格的修复范围ID 心智模型错误助手假设groupId是 0..N-1 的稠密数组下标然后在 87 个分组的项目里撞上了 600 多的 ID。事后见下节 D5查明groupId确实是稠密位置 ID真正稀疏的是Group.uniqueId——而 workspaces API 序列化分组引用时把uniqueId放在了 JSON 键groupId之下这个命名碰撞才是真正误导源头。截断与转录老化不可区分AI 运行时会把旧工具结果收缩为[result elided -- ask again if needed]桩该桩与字节预算截断通知长得一样导致助手反复重发相同的大结果调用。设计目标与非目标继承自 spec 原文规格 spec.md 列出的目标助手能用部分名称部分记得或推断出的子串找到任何项目实体——数据集、分组、动作、数据源、工作区、数据表——无需精确标题或路径能查看单个分组的内容其数据集标题 / id / 单位而不用拉取整个项目所有全项目列表都能分页使得默认调用在 570 数据集项目上返回可用、结构化、在预算内的结果而不是截断 preview助手能搜索 API 命令目录本身meta.search像人查手册目录一样而不仅是按精确名查命令助手对身份groupId、datasetId、uniqueId的文档化心智模型与运行时现实一致助手总能知道结果为什么不完整——太大truncated、分页windowed带nextOffset、还是老化elided——且每种状态都点名一个不同的恢复动作新原语必须可发现助手能通过它已在用的机制找到并正确调用它们。非目标同样重要划清了边界不做模糊、排序、语义或容错搜索v1 是朴素的大小写不敏感子串匹配不替代精确解析器getByPath/getByTitle/resolve仍是精确寻址路径搜索是喂给它们的发现步骤不搜索实时数据集值或遥测只搜项目结构/元数据与 API 目录不改热路径、数据模型或任何持久化项目格式。R1/R2project.search—— 一次遍历、类型化紧凑行核心命令project.search在当前仓库中的实现位于 ProjectDiscoveryCommands.cpp注册名与完整描述在registerCommands()中registry.registerCommand( QStringLiteral(project.search), QStringLiteral(Case-insensitive substring search across every project entity type: datasets (title, alias, units), groups, actions, sources, workspaces, and data tables (title/name). Returns compact typed rows -- never full objects -- with matchCount, window/nextOffset paging (default limit 20, max 100), and projectEpoch. THE starting point for finding anything in a large project; drill into hits with project.dataset.getByUniqueId / getByPath or project.group.get.), ...);参数与默认值源码实测值参数类型说明querystring必填大小写不敏感子串空串/纯空白是显式错误提示里直接点名project.group.list/project.dataset.list带 offset/limit或project.snapshot用于枚举typestring|array限定一种或多种dataset, group, action, source, workspace, table见parseTypeFilter的kValidTypes白名单groupIdinteger仅返回该位置型groupId下的数据集必须是 JSON 数字字符串会被拒绝——防止静默匹配错分组sourceIdinteger仅返回绑定到该sourceId的实体offsetinteger返回从第几个匹配开始默认 0limitinteger最大行数默认 20上限 100见kSearchDefaultLimit/kSearchMaxLimit匹配语义与一次遍历收集器matchesQuery()是所有实体类型共享的判定text.contains(query, Qt::CaseInsensitive)。数据集对title alias units三个字段做宽召回其余类型对标题/名称匹配。collectSearchRows()按固定顺序遍历ProjectModel的活状态访问器sources → groups → datasets → actions → workspaces → tables源码注释明确写了 The walk order is fixed ... so offset paging over an unchanged project is deterministic因此offset分页在未变更的项目上无缺口、无重复、可复现。每行是自定位的紧凑对象绝不含完整条目dataset 行typedataset、uniqueId、title、pathGroup/Dataset、groupId、groupTitle、index、units非空时若命中发生在 alias 或 units 而非 title 上行里会多一个matchedField字段说明为什么psia能搜到它appendDatasetRow中 titleHit/aliasHit/unitsHit 的互斥判定group 行typegroup、groupId位置型、uniqueId稳定型、title、datasetCountsource 行typesource、sourceId、titleworkspace 行typeworkspace、workspaceId、titleaction 行typeaction、actionId、titletable 行typetable、name、title。响应还携带matchCount全项目匹配总数不只是本页、有剩余时的nextOffset、一行_summary如 42 matches for CH- (showing 1-20)以及projectEpoch——与project.snapshot相同的单调计数器跨页调用者可以据此发现两页之间项目被改过、应当重头再来而不是信任撕裂视图。有命中时响应附_hint直接点名钻取命令Drill into a match: project.dataset.getByUniqueId{uniqueId} or project.dataset.getByPath{path} for datasets, project.group.get{groupId or uniqueId} for groups.R3project.group.get—— 单分组钻取双 ID 空间互斥选择器project.group.get与project.search同文件实现groupGet。它只读一个分组加一份紧凑的数据集摘要datasetId/uniqueId/index/title/units接受两个显式、互斥的选择器参数含义groupId位置型 ID0..N-1重排时整体平移project.group.update与数据集 CRUD 用的就是它uniqueId稳定的持久计数器删除/重排后不回收不复用可远大于分组数workspace 组件引用在 JSON 键groupId下携带的就是它offset/limit对datasetSummary分页默认 50上限 200——单个分组可能装 100 数据集不分页的摘要会在下一层复现 R5 失败源码里这段提示字符串值得原文照录kGroupIdSpacesHint它是 R6 身份文档要求的直接落地Pass exactly one selector: groupId (positional, 0..N-1, shifts on reorder; what project.group.update and dataset CRUD take) OR uniqueId (stable persisted counter; can be far larger than the group count). Workspace widget refs carry the groups uniqueId under the key groupId, so a large id read from workspace data belongs in this commands uniqueId parameter. Find valid ids via project.search or project.group.list.错误路径同样讲人话两个选择器都传、都不传、或 ID 不存在都会返回显式错误并带上上述双 ID 空间解释选择器传字符串而非 JSON 数字也会报错a string-typed id would silently resolve to group 0。成功响应同时返回两个 IDgroupIduniqueId助手一次调用即可把两个 ID 空间对齐。R4/R5三个列表命令获得分页且构造上就在预算内规格要求project.dataset.list、project.group.list、project.dataset.getExecutionOrder三个曾炸预算的命令接受可选offset/limit复用project.snapshot已确立的窗口化惯例。窗口化后响应永远报告全项目总数、有剩余时给nextOffset、附projectEpoch并通过window: {offset, count, total}块让分页响应自我声明是一页——助手不会把第一页误当成全集。一个关键的设计取舍plan 中的 Tradeoffs 表线上默认值保持不限量。TCP/SDK 客户端绕过 AI 助手路径旧集成测试期望全量列表如果在全局改默认值会静默破坏所有现有客户端。因此默认有界页由 AI 助手路径实现ToolDispatcher::executeCommandToolDispatch.cpp在助手调用这三个列表命令且未传limit时注入默认 limit新命令project.search/project.group.get则对所有调用方都默认有界。集成测试test_unpaged_calls_remain_complete专门验证了裸 TCP 不分页调用仍返回完整项目外加新增的 window/epoch 字段。R5 的构造性约束在 500 数据集的 fixture 项目上每个行大小有界的命令project.search、meta.search、project.group.get、project.dataset.list、project.dataset.getExecutionOrder用默认参数调用都返回结构化且在字节预算内的结果而不是truncated:true的字节前缀 preview按返回的nextOffset翻页能覆盖每一项。测试里的判据是紧凑 JSON 尺寸 3800 字节test_project_discovery.py 的test_compact_defaults_fit_budget且注释写明了校准后的助手端默认值dataset.list8→4、getExecutionOrder50→20、group.list计数上限 5。例外D6实测发现project.group.list的每一行内嵌该分组完整的嵌套datasets数组单行无界——一行就可能超过任何预算因此它只能可分页不能字节有界。保证在预算内的紧凑发现路径是project.search和project.group.get。同一轮实测还发现project.group.list此前从不暴露位置型groupIdserialize(Group)把位置字段省略了现已补进每行使列表结果可以直接喂给project.group.get{groupId}。R8meta.search—— API 目录自己的目录meta.search是助手工具面上的新元工具实现链路为dispatchMetaTool→runMetaSearch→ToolDispatcher::searchCommands合并目录在 ToolCatalog.cppassistantToolDefs()fsToolDefs()metaToolRoster() API 命令注册表跳过Safety::Blocked的命令。匹配规则是对每条命令的name description做大小写不敏感子串搜索按 name 排序——因为注册表是 QHash不排序的话迭代顺序随机、offset分页就不自洽。默认 limit 25上限 100。每行返回{ name: project.search, family: project, snippet: …描述前 120 字符… }family取命令名第一个.之前的段行的name可直接作为meta.describeCommand的参数。它补齐了发现-钻取闭环meta.search发现→meta.describeCommand钻取拿 schema→ 执行meta.searchDocs则是文档语料的语义搜索两个相邻名字互相区分命令目录 vs 文档页。空查询返回missing_query错误并提示用meta.listCommands枚举。meta.search必须与meta.describeCommand同处可用发现步骤和钻取步骤必须同行是 spec 的显式约束。R6/R7/R9身份文档、可发现性与自解释的不完整结果R6身份文档。规格在计划阶段被代码 ground truth 修正D5Group.groupId是位置型/稠密的稀疏身份是Group.uniqueIdworkspaces API 把uniqueId序列化在 JSON 键groupId之下——规格最初groupId 是稀疏的说法与报障助手犯的是同一个错误。修正后的要求落在文档上帮助手册的身份模型 Identity-Model.md 明确写有两套分组 ID 空间并警告在 workspace 数据里看到的大groupId其实是uniqueId不能传给位置型 ID 命令唯一例外是同时接受两者的project.group.get。R7可发现性对等。新命令注册进现有project.*读命令所在的注册表从而继承助手工具面、meta.describeCommandschema 路径与安全分级两个新命令在 command_safety.json 的safe层级中只读、自动执行、无确认门。命令助手看不见的原语没有意义。R9三种不完整三种措辞三种恢复状态响应措辞承诺恢复动作Windowed分页响应自我声明是一页并携带nextOffset用这个 offset 再调一次Truncated超字节预算通知指明结果太大并点名该命令的分页/过滤参数收窄调用永不原样重试Aged out转录老化收缩桩说明原始调用成功仅为节省转录空间被折叠仅在再次需要该数据时重发此外新的发现型结果project.search、project.group.get、meta.search加入永不收缩never-elided集合——该集合的实现见 HistorySurgery.cpp 中isDiscovery豁免判定与fs.*内容同列。豁免之所以安全是因为这些结果构造上有界R5spec 显式警告豁免绝不能扩展到任何结果大小无界的命令否则转录会爆炸。约束与不变量spec 原文的护栏只读所有新增/扩展命令只读项目模型或命令目录不触碰 epoch 门控的变更/自动保存路径必须读活状态而非可能过期的缓存快照。构造上在预算内是判定约束响应形状的正确性由默认分页下装得进字节预算定义而不是靠调用者挑小切片。发现能力对等助手看不见或被确认门挡住的命令等于不存在。无热路径影响、无新第三方依赖、无持久格式变更plan 确认全部代码运行在主线程 API 处理器 / 元工具分发上只 const 读ProjectModel不触碰FrameReader/CircularBuffer/FrameBuilder/Dashboard。分页惯例一致性复用offset/limit/nextOffset/projectEpoch这套project.snapshot已确立的形状不发明第二套约定。实现落点与验证路径规格四阶段工作流中plan.md 给出了文件级落点仓库后续重组过目录以下为当前树中可确认的对应文件关注点当前仓库位置project.search/project.group.get处理器ProjectDiscoveryCommands.cpp / ProjectDiscoveryCommands.h列表命令窗口化ProjectListCommands.cppmeta.search目录搜索ToolCatalog.cppsearchCommands、MetaToolRunner.cpp助手端默认 limit 注入与截断/收缩措辞ToolDispatch.cpp、HistorySurgery.cpp安全分级safe 层command_safety.json第 117、136 行可见project.group.get、project.searchAI 静态面测试test_ai_assistant_static.py集成验证test_project_discovery.py 用 API server 对着一个按现场报告形状合成的87 分组 / 570 数据集fixture分组 40–42 模拟压力仪表psia 单位、一个PT-ALPHAalias、一个标题含 Pressure 的数据集分组uniqueId从 600 起刻意与位置型groupId拉开差距逐条验收 AC1–AC5。运行前提应用开启 Settings → Miscellaneous → Enable API Serverlocalhost:7777。值得记住的几条断言test_search_basic搜 pressure 返回含 group/dataset/action 三类行的类型化结果且 dataset 行的path能再被project.dataset.getByPath解析回同一uniqueId发现 → 精确钻取的闭环test_search_matched_field_provenancealias 命中带matchedField: aliasunits 命中带unitstitle 命中不带该字段test_search_paging_is_deterministicnextOffset走完全集无缺口无重复重复调用返回相同页test_group_get_both_id_spaces同一分组经位置型groupId与稳定uniqueId解析响应同时携带两个 ID 且datasetCount 7test_list_paginglimitN恰返 N 条、window.total保持全项目总数、getExecutionOrder的position序列与 offset 对齐test_compact_defaults_fit_budget四个有界行命令的默认页紧凑尺寸全部 3800 字节test_group_list_is_paged_not_byte_boundedgroup.list的 D6 例外——它保证分页window {offset:0, count:5, total:87}、nextOffset5不保证字节上界。AC6文档校验由scripts/documentation-verify.py对编辑后的身份文档跑通过验证AC7/AC8/AC9 的静态半schema 可描述、安全分层、三种通知措辞互异由tests/scripts/test_ai_assistant_static.py覆盖AC8/AC9 的实盘转录观察标注为维护者验证项。适用边界与已知取舍所有描述以当前仓库代码为准project.search默认 limit 20/上限 100、project.group.get默认 50/上限 200、meta.search默认 25/上限 100均可用参数覆盖v1 搜索是朴素子串匹配无相关性排序、无模糊容错——规格把它明确列为后续增强不是缺失project.group.list仍是唯一分页但非字节有界的列表命令紧凑钻取请优先project.searchproject.group.get字节预算本身是供应商相关的默认约 4 KB钳制 2–16 KB默认页在预算内是助手路径的构造性保证裸 TCP/SDK 客户端不分页时仍拿到全量列表向后兼容meta.search只覆盖未处于Safety::Blocked的命令被禁命令不出现在搜索结果里。这套原语的意义不止于修一个会话 bug它把助手在大项目里导航从全量倾倒 撞截断变成搜索 → 类型化紧凑行 → 精确钻取的三段式流程并用projectEpoch、matchCount、window自描述字段让每一页结果对自己的可信度负责——这些正是 spec 0012 标题里 discoverability primitives 的确切含义。【免费下载链接】Serial-StudioOpen-source telemetry dashboard. Supports UART, BLE, MQTT, Modbus, CAN Bus and more.项目地址: https://gitcode.com/GitHub_Trending/se/Serial-Studio创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表