十年匠心定制 · 商业建站与技术教学双线并行 咨询热线:400-886-1026 service@lmnt.cn
ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

Hindsight Entity Labels 实战指南:用受控词表为记忆自动打标与分类

Hindsight Entity Labels 实战指南:用受控词表为记忆自动打标与分类 Hindsight Entity Labels 实战指南用受控词表为记忆自动打标与分类【免费下载链接】hindsightHindsight: Agent Memory That Learns项目地址: https://gitcode.com/GitHub_Trending/hindsight2/hindsight导读本文基于 Hindsight 官方技术博客《Using Entity Labels to Automatically Tag Memories in Hindsight》展开系统讲解 Entity Labels实体标签这一银行级bank-level分类能力的核心概念、四种标签类型、底层提取原理与端到端实战配置。读完本文你将掌握如何通过一份 bank 配置把自由文本记忆变成统一、可筛选的结构化分类并让标签成为召回recall的过滤器。为什么需要 Entity Labels自由实体提取的痛点Hindsight 的自由式free-form实体提取非常擅长发现数据里有什么——模型自主识别出的名字、地点、概念。但当你要真正筛选这些数据时自由实体反而成了问题你写了一个 ingest 工单的支持 Agent。三个客户都打电话提到了 Acme Corp。第一个会话记住了Acme Corp第二个记住了Acme第三个记住了Acme Corporation。它们是同一家公司但实体字符串不一致导致下游查询所有与 Acme 相关的内容时三条记忆中只随机返回一条。这就是自由词表的拼写漂移问题同一概念在不同会话中被表述成不同字符串图聚类与检索随之失效。Entity Labels 的解法在银行bank级别定义一个受控词表——一组固定的分类维度如priority、sentiment、product_area及其允许取值。在 retain 阶段LLM 被强制从该词表中取值。结果是每条记忆都获得一致的、可查询的分类且无需改动任何 Agent 代码。Entity Label 是什么一个分类维度的最小模型一个标签组label group就是银行上的一个分类维度。它包含key维度名如prioritytype值的形态value/multi-values/text/mapvaluesenum 型分组允许取值的列表最小的完整配置如下{ entity_labels: [ { key: priority, description: Urgency of the support request, type: value, values: [ { value: low }, { value: medium }, { value: high }, { value: urgent } ] } ] }当该银行 retain 一条形如customers checkout is broken, cant process orders的工单时LLM 从四个允许值中选一个Hindsight 随后存储一条与记忆关联的实体其canonical_name priority:urgent。两条都被分类为 urgent 的记忆因此在知识图谱中共享同一个实体——它们自然聚类、检索时被一并找到你也可以查询整个银行内所有 urgent 的内容。从源码看这个模型由 hindsight-api-slim/hindsight_api/engine/retain/entity_labels.py 中的 Pydantic 类承载LabelValue单个允许值、MapFieldmap 字段支持递归、LabelGroup标签组含optional与tag两个布尔开关、EntityLabelsConfig整个受控词表。其中LabelGroup的完整定义还支持一个文档示例之外的类型——multi-text开放词表的多选文本以及optional: bool True的默认行为详见源码第 33-42 行。四种标签类型每个标签组的type有四种取值选择匹配维度形态的那一种。value—— 单选枚举默认类型。LLM 从允许值中恰好选一个当没有适用项时跳过前提是optional: true这也是默认值。{ key: sentiment, description: Customers emotional tone in the ticket, type: value, values: [ { value: frustrated }, { value: neutral }, { value: appreciative } ] }存储形态sentiment:frustrated、sentiment:neutral或sentiment:appreciative。multi-values—— 多选枚举与单选相同的思想但 LLM 在多个值都适用时可以选取多个。{ key: product_area, description: Which product areas the ticket touches, type: multi-values, values: [ { value: billing }, { value: auth }, { value: dashboard }, { value: api }, { value: mobile } ] }一张工单可以产出多个实体product_area:billing、product_area:dashboard并将共享任一区域的记忆链接起来。text—— 已知键下的自由文本每次都用相同的键前缀但值本身是开放词表。适用于想要统一前缀topic:、customer_name:但又无法枚举所有取值的维度。{ key: customer_name, description: Customer or company mentioned in the ticket, type: text, values: [] }存储为customer_name:Acme Corp、customer_name:Globex等。代价图聚类的可靠性不如枚举——因为模型可能在不同会话中用不同的措辞表达同一值这是开放词表必然的取舍。map—— 结构化实体v0.6.1当单个实体有多个具名字段时使用——比如一个人有姓名和角色一个客户有层级和账号 ID。每个字段自身也是带类型的因此可以混用text、枚举甚至嵌套的map。{ key: customer, description: Customer mentioned in the ticket, type: map, fields: { name: { type: text, description: Customer or company name }, tier: { type: value, values: [ { value: free }, { value: pro }, { value: enterprise } ]}, account_id: { type: text, description: Account or organization ID } } }每个提取出的字段被存储为扁平的key:field:value实体——customer:name:Acme Corp、customer:tier:enterprise、customer:account_id:org_8f4a。扁平编码意味着 map 字段与单值标签一样参与知识图谱和检索底层无需任何 schema 变更。从源码看map 的递归建模由 entity_labels.py 中的_build_map_fields_model实现text字段映射为str | Nonevalue字段映射为Literal[...] | Nonemulti-values映射为list[Literal[...]]嵌套map则递归生成list[NestedModel]。提取是如何工作的三步流水线整个流水线简洁且易于推理第 1 步银行配置编译成 Pydantic 模型。当你用entity_labels块调用update_bank_config时Hindsight 将其解析为EntityLabelsConfig并用build_labels_model()生成一个动态 Pydantic 类每个标签组对应一个类型化字段。枚举组变成Literal[...]多选组变成list[Literal[...]]map 组变成list[NestedModel]。该函数位于 fact_extraction.py 的调用点其核心实现见 entity_labels.py。第 2 步retain 的 LLM 调用使用 JSON-schema 强制。动态 Pydantic 模型被挂到提取调用的结构化输出 schema 上由 provider 强制执行——对枚举组而言模型在字面上无法返回词表之外的取值。与 schema 一起下发到 prompt 的段落长这样══════════════════════════════════════════════════════════════════════════ ENTITY LABELS - CLASSIFICATION ATTRIBUTES ══════════════════════════════════════════════════════════════════════════ Classify each fact using the structured labels field below. Continue extracting regular named entities in the entities field. For each fact, fill the labels object. Each field is a label group: - priority (single value or null): Urgency of the support request • low • medium • high • urgent - product_area (multi-value (list)): Which product areas the ticket touches • billing • auth • dashboard • api • mobile Only assign labels when clearly applicable. Leave null/empty if the fact does not match.这段 prompt 由 fact_extraction.py 的_build_labels_prompt_section动态生成每个非 map 标签组渲染一行- {key} ({mode}): {description}并枚举取值map 组则被渲染到独立的 STRUCTURED ENTITY TYPES 段落。注意每个value还支持可选的description字段会以— {description}的形式拼到取值后面直接参与 prompt 塑造。第 3 步后处理校验并写实体。LLM 响应以每个 fact 一个结构化labelsdict 的形式返回。Hindsight 用预构建的labels_lookup集合由配置中的枚举构建逐一校验取值丢弃词表外的内容递归处理 map 类型然后为每个命中的值写一条实体。结果落入unit_entities连接表——这条表原本就支撑着自由实体检索标签并不需要特殊的存储。与自由实体完全相同的形态完全相同的检索路径只是字符串变得可预测了。tag: true的收益标签即过滤器默认情况下标签以实体形式存在。给标签组加上tag: true后命中的key:value还会被写入记忆的tags字段——于是你可以像筛选任意用户标签那样按标签筛选召回结果。{ key: priority, type: value, tag: true, values: [ { value: low }, { value: medium }, { value: high }, { value: urgent } ] }retain 一张工单后记忆自动带上tags [priority:urgent, ...]。然后results client.recall( bank_idsupport, queryWhats the most pressing issue with billing right now?, tags[priority:urgent], tags_matchall, )召回被限定在携带该标签的记忆内。把priority与一个 sentiment 标签搭配你就可以用两个标签 一条查询问出what urgent tickets had frustrated customers this week?。只对你真正计划筛选的维度设置tag: true。每个标签都会成为记忆可筛选面的一部分过度打标只会让筛选面变噪却不增加多少检索价值。从实现层面看标签注入由 fact_extraction.py 的_inject_label_tags完成它用label_tag_keys()收集所有tag: true的组键再用split_label_tags()从实体的key:value字符串中筛出属于这些组的条目去重后追加到 fact 的tags。而 fact_storage.py 在存储/重提取时借助label_tag_keys区分派生自标签的 tag与调用方提供的 tag避免重提取时误删或误改标签派生的条目。tags_match参数在 api/http.py 等处的定义支持anyOR默认、allAND与exact三种组合语义。仅标签模式Labels-Only Mode默认情况下标签实体与自由实体并行写入——自由实体是 LLM 自主发现的人、地点、概念。如果你只想要标签、别无其他追求分析级一致性、下游 BI 管道、确定性仪表盘把entities_allow_free_form设为false{ entity_labels: [ /* … */ ], entities_allow_free_form: false }此时银行只会浮出受控词表中的实体自由提取在源头就被抑制——无需事后过滤。源码层面的佐证在 fact_extraction.py当free_form_entities为假时动态 schema 中的entities字段被替换为list[str]其 Field 描述直接写明 Leave empty — labels-only mode。设计词表的原则综合生产环境的大量观察几条经验法则从两到四个维度起步。之后可以再加但标签越多每次 retain 调用消耗的 LLM token 越多模型花在分类上的注意力也会挤占事实提取。先选你确定会筛的维度。优先用枚举value/multi-values而非text。枚举保证同一概念得到同一字符串——这正是标签的全部意义。只有当值空间真正开放人名、自由主题、产品 SKU时才用text。带子字段的实体用map。人、组织、地址、客户档案——任何你原本会往扁平字符串里塞结构化数据的地方。只对要按标签筛选召回的维度设置tag: true。筛选是收益标签噪声是成本。善用description字段。它们被直接注入 LLM prompt对提取质量的塑造超过其他任何因素。说清楚每个标签的含义和适用时机。一个稳定性要点自 Hindsight v0.7.0 起用户自定义的标签实体豁免于模糊解析。priority:urgent永远是priority:urgent——它不会被 consolidator 合并进一个相似外观的实体。这让标签可以放心地作为跨分析任务、告警规则和仪表盘的长生命周期标识符来依赖。端到端实战一个支持工单银行把前面所有概念组合起来。下面是一个支持 Agent 的完整配置沿四个维度对工单分类client.update_bank_config( bank_idsupport, entity_labels[ { key: priority, description: Urgency of the support request, type: value, tag: True, values: [ {value: low}, {value: medium}, {value: high}, {value: urgent}, ], }, { key: sentiment, description: Customers emotional tone in the ticket, type: value, values: [ {value: frustrated}, {value: neutral}, {value: appreciative} ], }, { key: product_area, description: Which product areas the ticket touches, type: multi-values, tag: True, values: [ {value: billing}, {value: auth}, {value: dashboard}, {value: api}, {value: mobile}, ], }, { key: customer, description: Customer mentioned in the ticket, type: map, fields: { name: {type: text, description: Customer or company name}, tier: {type: value, values: [ {value: free}, {value: pro}, {value: enterprise} ]}, account_id: {type: text, description: Account or org ID}, }, }, ], )retain 一张工单client.retain( bank_idsupport, content( Acme Corp (enterprise, account org_8f4a) reports their checkout is completely broken — customers cant process orders. Theyve been blocked for 40 minutes and are extremely frustrated. Billing dashboard shows the right plan, but the API rejects every charge attempt with a 500. ), )提取完成后这条记忆携带以下实体priority:urgent sentiment:frustrated product_area:billing product_area:api customer:name:Acme Corp customer:tier:enterprise customer:account_id:org_8f4a以及这些标签因为priority和product_area设置了tag: true[priority:urgent, product_area:billing, product_area:api]现在按标签召回results client.recall( bank_idsupport, queryWhat urgent issues are blocking customers right now?, tags[priority:urgent], )这个查询是语义 标签双重过滤的你得到模型认为相关的每条记忆但被限制在标记为 urgent 的范围内。再加一个标签——tags[priority:urgent, product_area:billing]——过滤进一步收紧。核心思想回顾自由实体提取告诉你LLM 注意到了什么。Entity Labels 告诉你你在乎什么——每次都一样用同一套词表。加上tag: true这套词表就同时成为每条记忆上的可筛选索引加上map你可以在不引入独立 schema 的情况下建模丰富的结构化实体加上entities_allow_free_form: false你就得到一个分析级干净、没有词表外噪声的银行。两处银行配置改动零 Agent 代码改动每条记忆上持续存在的分类。这就是 Entity Labels 的全部主张。延伸阅读Map-Type Entity Labelsv0.6.1——结构化实体诞生的版本说明Stable User-Defined Label Entitiesv0.7.0——为什么标签能在 consolidation 后存活The Constellation Graph View——可视化查看你的标签实体源码实现entity_labels.py模型构建与词表校验、fact_extraction.pyprompt 与 schema 装配、标签注入测试覆盖test_entity_labels.pybuild_labels_model对单选、多选、混合、空值、开放词表等场景的断言【免费下载链接】hindsightHindsight: Agent Memory That Learns项目地址: https://gitcode.com/GitHub_Trending/hindsight2/hindsight创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表