
人工智能AI AgentAgent 框架工具调用Agent 工作流RAGMCP Clients强化学习【免费下载链接】agent-core-javaopenJiuwen agent core Java是 openJiuwen Core的 Java版本提供AI Agent开发、运行、调优与演进相关的全套SDK能力。项目地址https://gitcode.com/openJiuwen/agent-core-java点击查看免费下载在基于向量检索的 RAGRetrieval-Augmented Generation方案中纯文本块召回难以捕捉实体—关系—实体之间的结构化语义。com.openjiuwen.retrieval.common.Triple是 openJiuwen agent-core-java 检索模块中承载知识图谱三元组的核心数据模型它以subject主语、predicate谓词、object宾语三个必填字段和可选的metadata元数据为GraphKnowledgeBase的图模式索引构建与图扩展检索提供了统一的数据载体。读完本文你可以掌握Triple的字段定义、构造与校验规则、元数据使用惯例以及它在三元组抽取、图索引构建、图扩展检索整条链路中的具体作用从而在 Java 项目里正确构建并调试图谱增强检索能力。一、Triple 在检索模块中的定位Triple位于 Triple.java其类注释标明它镜像 Python 版openjiuwen/core/retrieval/common/triple.py中的同名类属于 Java 版与 Python 版行为对齐parity的实现。该模型在整个检索链路中承担关系原子的角色索引侧GraphKnowledgeBase开启图模式useGraphtrue后切分出的TextChunk会经由Extractor抽取为ListTriple再由知识库转换为文本块写入独立的三元组索引检索侧GraphRetriever通过三元组索引召回相关关系并借助三元组中的实体首尾做图扩展beam search最终把扩展到的文本块与原召回结果做 RRF 融合配套模型与Triple同包下的 TripleBeam.java一条三元组路径及其评分和 TripleMemory.javaAgenticRetriever 中用于多轮改写时缓存已见三元组都围绕该模型工作。原文档Triple.md说明subject、predicate、object均不能为空GraphKnowledgeBase图模式索引与检索依赖该模型。下面结合源码逐层展开。二、字段结构与构造规则2.1 字段一览从 Triple.java 的源码看Triple是一个普通 POJO包含四个成员字段类型是否必填说明subjectString是主语即关系的起点实体predicateString是谓词即实体间的关系描述objectString是宾语即关系的终点实体metadataMapString, Object否附加元数据默认初始化为空的LinkedHashMap用于携带doc_id、chunk_id等溯源信息需要说明的是原文档描述中提到可选置信度但从当前 Java 源码看Triple并未单独定义 confidence 字段如果需要保存置信度一类的数值信息可以推断应通过metadata中的自定义键承载这一点请以实际代码为准。2.2 构造器与校验Triple提供三个构造入口见 Triple.javapublic Triple() { } public Triple(String subject, String predicate, String object) { this(subject, predicate, object, null); } public Triple(String subject, String predicate, String object, MapString, Object metadata) { this.subject requireText(subject, subject); this.predicate requireText(predicate, predicate); this.object requireText(object, object); setMetadata(metadata); }校验逻辑由私有静态方法requireText完成Triple.javaprivate static String requireText(String value, String fieldName) { if (value null) { throw RetrievalExceptions.validation(fieldName is required); } return value; }几个使用上需要注意的行为空值快速失败subject、predicate、object任一为null时构造器立即抛出RetrievalExceptions.validation生成的BaseError错误信息形如subject is required属于构造即校验的防御式设计metadata 防御性拷贝setMetadata会对入参做一次浅拷贝new LinkedHashMap(metadata)传null时回退为空LinkedHashMap。这保证外部修改原始 Map 不会影响已构造的Triple内部状态LinkedHashMap 保持插入序元数据采用LinkedHashMap而非HashMap遍历metadata时顺序与插入顺序一致便于日志排查和序列化输出稳定全量 getter/setter三个文本字段与metadata均提供标准访问器setter 不做二次校验因此在运行时通过setSubject(null)写入空值是允许的校验只发生在构造阶段。基本用法示例// 最简构造metadata 为空 Map Triple triple new Triple(Alice, knows, Bob); // 带溯源元数据的构造 Triple withMeta new Triple( Elden Ring, publisher, FromSoftware, Map.of(doc_id, doc_1, chunk_id, chunk_7));以上用法与单元测试 TripleTest.java 完全一致测试createTripleUsesEmptyMetadataDefault验证了三参构造后metadata为空createTripleWithMetadataStoresMetadata验证了元数据完整存储missingRequiredFieldsAreRejected则断言(null, null, null)、(Alice, null, null)、(Alice, knows, null)三种缺字段场景均抛出BaseError。三、metadata 的约定键溯源三元组来源Triple本身只是载体真正的语义来自metadata中约定俗成的键。在仓库中两个抽取器和知识库都统一使用了doc_id与chunk_id两个键用于把三元组回溯到来源文档与文本块TripleExtractor.parseTriples在解析 LLM 输出后为每个三元组写入Map.of(doc_id, docId, chunk_id, chunkId)见 TripleExtractor.javaLLMTripleExtractor.parseTriples在复制 chunk 原有 metadata 的基础上再覆盖写入doc_id、chunk_id见 LLMTripleExtractor.javaSimpleTripleExtractor同样遵循该惯例并额外写入序列化后的triple键见下文。这种约定键机制使三元组索引中的每条记录都能反查回kb_kbId_chunks中的原文块是后续图扩展检索由三元组找回关联 chunk能够成立的根基。四、Triple 的生成三种 Extractor 实现Triple实例不是手工逐条构造的而是由索引管线的Extractor从TextChunk批量抽取而来。retrieval模块提供了三种实现基类为 Extractor.java4.1 TripleExtractor基于 LlmInvoker 的 LLM 抽取TripleExtractor.java 是功能最完整的实现提示词工程内置PROMPT_TEMPLATEL39-L144要求 LLM 从标题 段落中构造 RDF 风格图输出严格 JSON顶层恰好含named_entities与triples两个键triples中每项是恰好三个字符串的数组模板还内置了两个 few-shot 示例Magic Johnson、Elden Ring并要求能解析代词为具体名称不要输出重复三元组等并发控制每个 chunk 的抽取任务提交到名为triple-extractor-io的有界模块线程池OpenJiuwenExecutors.newBoundedModulePool并用Semaphore限制最大并发默认 50容错解析parseTriples先做normalizeJsonContent清理剥离 Markdown 代码围栏、去除尾逗号再逐项校验三元组是否为恰好三元素的数组且三个元素均非 null/容器节点非法项计数并告警跳过解析整体失败时抛出RETRIEVAL_KB_TRIPLE_EXTRACTION_PROCESS_ERROR单 chunk 失败策略单个 chunk 抽取失败会被记录为该 chunk 的错误并在mergeResults中抛出首个错误同时保留其他 chunk 已成功抽取的三元组逻辑上可见于日志。构造参数为TripleExtractor(LlmInvoker llmClient, String modelName)或带temperature默认 0.0与maxConcurrent的四参形式其中LlmInvoker是类内定义的函数式接口便于测试注入 mock 客户端。4.2 LLMTripleExtractor直连 BaseModelClient 的变体LLMTripleExtractor.java 与上述实现同源区别在于它直接依赖BaseModelClient并通过自建的ThreadPoolExecutor核心 0、最大maxConcurrent、SynchronousQueue、CallerRunsPolicy并发抽取。其extractJson/repairJson对 LLM 输出做了更强的兜底先剥离代码围栏再按最外层数组优先、否则取最外层对象的策略截取 JSON 片段最后用正则修复尾逗号。解析成功后同样以node.get(0/1/2).asText().trim()生成Triple并把 chunk 原有 metadata 合并进三元组元数据。4.3 SimpleTripleExtractor无 LLM 的规则兜底SimpleTripleExtractor.java 不调用任何模型按句子边界.!?。之后的空白见SENTENCE_SPLIT切分文本将每句按空白拆词第 1 个词作subject、第 2 个词作predicate、其余拼作object。它显式把序列化后的三元组写入metadata.put(triple, ...)供下游直接解析。该实现适合作为离线测试、低质量语料的兜底方案其输出质量明显低于 LLM 抽取选型时应注意。三者对应的 API 文档见 LLMTripleExtractor.md 与 SimpleTripleExtractor.md。五、下游消费GraphKnowledgeBase 如何把 Triple 变成索引GraphKnowledgeBase.java 是Triple最主要的生产者和消费者。5.1 索引构建链路addDocuments的流程L76-L129为校验chunker、indexManager非空缺少时抛出RETRIEVAL_KB_CHUNKER_NOT_FOUND/RETRIEVAL_KB_INDEX_MANAGER_NOT_FOUND若文档无 id则用UUID.randomUUID()补齐chunker.chunkDocuments切分后以kb_kbId_chunks为索引名构建 chunk 索引仅当config.isUseGraph() true且注入了extractor时才执行extractor.extract(chunks)并把得到的ListTriple交给buildTripleIndex。buildTripleIndex与tripleChunks展示了Triple到存储层的转换细节L313-L352private ListTextChunk tripleChunks(ListTriple triples) { for (int index 0; index triples.size(); index) { Triple triple triples.get(index); String text triple.getSubject() triple.getPredicate() triple.getObject(); MapString, Object metadata new LinkedHashMap(triple.getMetadata()); metadata.put(triple, serializeTriple(triple)); // JSON: [s,p,o] metadata.put(chunk_index, index); ... chunks.add(new TextChunk(UUID.randomUUID().toString(), text, docId, metadata)); } }要点每个Triple被拼成subject predicate object形式的纯文本作为向量化/BM25 的索引文本原始三元组以 JSON 数组字符串形式存入metadata.triple这是GraphRetriever后续 beam 搜索时重建实体边的关键parseTripleStrict会按 JSON 数组反解析该字段metadata.chunk_id直接继承自抽取阶段写入的来源 chunk id形成三元组 → 原文块的反向指针三元组索引用kb_kbId_triples命名tripleIndexName()与 chunk 索引kb_kbId_chunks分离存储。5.2 删除链路deleteDocumentsL191-L225对每个docId先删 chunk 索引若useGraph为真则再删kb_kbId_triples中的对应记录三元组删除失败仅记录warn日志不阻断整体流程。updateDocuments则是先删后加的组合操作天然保证三元组索引随文档更新而刷新。5.3 统计能力getStatisticsAsync会在useGraphtrue时同时返回chunk_index_info与triple_index_info便于运维侧核对三元组索引规模L237-L261。六、检索侧三元组索引如何驱动图扩展GraphKnowledgeBase.retrieve在useGraph生效时构造 GraphRetriever其graphExpansion逻辑L191-L287完整体现了三元组索引的检索价值先召回 chunk按vector/sparse/hybrid模式从 chunk 索引取初始结果由 chunk 反查三元组fetchTriples收集命中 chunk 的chunk_id以chunk_ids过滤条件从三元组索引拉取候选三元组beam search 图扩展TripleBeamSearch同文件内 L581 起把每条三元组的metadata.triple解析回[subject, predicate, object]取首尾两个实体作为查询词继续检索相邻三元组逐跳扩展出TripleBeam路径默认num_beams10、num_candidates_per_beam100、max_length即graph_hops默认 2encoder_batch_size256扩展路径的得分用 query 向量与路径拼接文本向量的余弦相似度计算回捞并融合扩展出的三元组再经fetchChunks反查回原文块与新 chunk 一起通过FusionUtils.rrfFusionRetrievalRRF k60融合最后截断到topK。整个过程中Triple的metadata.chunk_id与metadata.triple两个约定键被反复使用——前者保证三元组↔原文块的双向可达后者保证实体边的可解析性。此外RetrievalConfig中的graphExpansion开关会经optionsFrom透传给检索器L354-L364开启agentic时则由AgenticRetriever接管其中TripleMemoryTripleMemory.java以小写归一化的三元组字符串去重把已见关系以(s p o)文本形式喂给查询改写模型避免多轮循环检索重复引用同一关系。相关 API 文档可进一步参阅 GraphRetriever.md、TripleBeamSearch.md、TripleBeam.md、TripleMemory.md 与 GraphKnowledgeBase.md。七、工程实践要点小结结合源码与测试使用Triple时有几条可直接落地的建议构造时机优先使用带 metadata 的四参构造器若手工构造三元组如从外部图谱导入务必自行补齐doc_id/chunk_id否则图扩展阶段将失去回捞原文块的能力空值语义校验只拦null不拦空串若上游 LLM 可能返回空字符串三元组建议在进入GraphKnowledgeBase前自行过滤metadata 可变性getMetadata()返回的是内部引用setter 做了拷贝getter 未做外部代码应避免直接修改已注册三元组的 metadata以免污染索引构建时的序列化输出抽取器选型正式图谱构建用TripleExtractor/LLMTripleExtractor质量高、有并发与容错离线调试或无模型环境用SimpleTripleExtractor兜底验证方式修改Triple相关逻辑后可运行 TripleTest.java 与 GraphKnowledgeBaseTest.java其中使用KnowledgeBaseConfig.builder().kbId(graph).useGraph(true).build()验证图模式链路做回归确认。八、相关文档索引模型文档Triple.md、TextChunk.md、RetrievalConfig.md、KnowledgeBaseConfig.md抽取器文档Extractor.md、LLMTripleExtractor.md、SimpleTripleExtractor.md检索文档GraphKnowledgeBase.md、GraphRetriever.md综上Triple虽是一个字段极少的轻量模型但它是 agent-core-java 图谱增强检索的枢纽数据结构其构造即校验保证了索引数据的干净性metadata中doc_id/chunk_id/triple三枚约定键串联起抽取 → 索引 → 图扩展 → 回捞融合的完整链路是理解并定制GraphKnowledgeBase行为不可绕开的一环。赞分享人工智能AI AgentAgent 框架工具调用Agent 工作流RAGMCP Clients强化学习【免费下载链接】agent-core-javaopenJiuwen agent core Java是 openJiuwen Core的 Java版本提供AI Agent开发、运行、调优与演进相关的全套SDK能力。项目地址https://gitcode.com/openJiuwen/agent-core-java点击查看免费下载相关推荐openJiuwen agent-core 知识图谱三元组数据模型 Triple 深度解析从字段定义到图检索全链路实践openJiuwen agent core 知识图谱三元组数据模型 Triple 深度解析从字段定义到图检索全链路实践 本文围绕 openJiuwen age人工智能AI AgentAgent 框架大模型工具调用RAG提示工程强化学习openJiuwen agent-core-java 图知识库 GraphKnowledgeBase 实战指南三元组抽取、图索引与多跳扩展检索openJiuwen agent core java 图知识库 GraphKnowledgeBase 实战指南三元组抽取、图索引与多跳扩展检索 本文以 com人工智能AI AgentAgent 框架工具调用Agent 工作流RAGMCP Clients强化学习openJiuwen agent-core Extractor 抽象基类解析LLM 驱动的 RDF 三元组抽取与知识图谱索引openJiuwen agent core Extractor 抽象基类解析LLM 驱动的 RDF 三元组抽取与知识图谱索引 本篇文章聚焦 openJiuwe人工智能AI AgentAgent 框架大模型工具调用RAG提示工程强化学习上一篇Apache APISIX 版本演进全览从 0.6.0 到 3.18.0 的变更记录深度解析下一篇Swift 标准库 Buffer API 重命名演进SE-0114 如何将 Value 更名为 Header创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考