
人工智能AI AgentAgent 框架大模型工具调用RAG提示工程强化学习【免费下载链接】agent-coreopenJiuwen agent-core可提供AI Agent开发、运行、调优与演进相关的全套SDK能力项目地址https://gitcode.com/openJiuwen/agent-core点击查看免费下载本文围绕 openJiuwen agent-core 图记忆Graph Memory能力中的核心模块openjiuwen.core.memory.graph.extraction展开它负责从对话、文档与 JSON 三类来源中抽取实体与关系并为记忆图提供结构化输入。读完本文你将掌握该模块的分层结构多语言响应模型基类MultilingualBaseModel、实体/关系类型定义、抽取用 Pydantic 输出模型、线程安全的提示词模板管理器、按情节类型组装提示词的入口函数以及 LLM 回复的 JSON 容错解析工具并能结合仓库中的调用链与测试用例理解其在GraphMemory写入流水线中的实际位置。一、模块定位图记忆流水线中的结构化输入引擎在 openJiuwen agent-core 中图记忆由 graph_memory/base.py 中的GraphMemory类承载它维护一张覆盖用户对话与文档的知识图谱通过 LLM 抽取实体与关系、执行合并与去重并支持实体/关系/情节的语义检索。而extraction模块正是这条流水线的输入端——所有进入记忆图的实体与关系都先由它完成从原始文本到结构化声明的转换。从调用关系看GraphMemory.add_memory的完整流程见 graph_memory/base.py依次经过时区预测extract_timezone——为后续关系抽取中的相对时间解析提供时区参考实体声明抽取extract_entity_declaration——识别当前消息/文档/JSON 中的实体名称与类型关系抽取extract_relation_declaration——在实体列表之上抽取带时间信息的事实三元组实体去重与合并dedupe_entity_list、merge_existing_entities——与库中已有实体比对并归并实体摘要与属性抽取extract_entity_attributes关系过滤与去重filter_relations_for_merge、dedupe_relation_list。每一步的 LLM 调用都遵循同一范式由extraction_prompts中的组装函数返回(模板变量, PromptTemplate, LLM 响应格式)三元组交由_invoke_llm执行最后用parse_response.parse_json将回复解析回结构化数据见 graph_memory/base.py 中parse_all_relations(ensure_list(parse_json(...)))的典型组合。因此理解extraction模块是掌握图记忆写入链路的前提。二、MultilingualBaseModel多语言响应模型基类openjiuwen.core.memory.graph.extraction.base.MultilingualBaseModel是所有抽取输出模型的基类base.py。它基于 PydanticBaseModel在保留字段校验能力的同时解决了两个问题多语言描述替换与将输出模型转为 LLM 可消费的字符串/结构化格式。其多语言描述来源于模块级字典MULTILINGUAL_DESCRIPTION由 prompts/entity_extraction/cn.py 与 prompts/entity_extraction/en.py 在调用register_language()时填充。模型字段中的description{{[rel_name]}}这类占位符会被替换为对应语言的实际描述例如中文该实体联系的名称、英文Name of factual relation。2.1 multilingual_model_json_schema按语言生成 JSON Schemadef multilingual_model_json_schema(cls, language: str cn, strict: bool False, **kwargs) - dict[str, Any]languagestr可选语言标识如cn、en默认cnstrictbool可选是否启用严格模式默认Falsekwargs透传给 Pydanticmodel_json_schema的额外参数。实现上base.py先生成标准 Pydantic schema再用_recursive_replace把description按MULTILINGUAL_DESCRIPTION[language]递归替换。strictTrue时通过 BFS 遍历 schema 树为所有type object且含properties的节点强制写入additionalProperties: False并自动补齐required字段列表——这正是 OpenAI 结构化输出格式的要求。对应单元测试 tests/unit_tests/core/memory/graph/extraction/test_base.py 中_object_nodes_with_wrong_additional_properties专门校验了这一点。2.2 readable_schema生成 LLM 可读的 schema 文本def readable_schema(cls, language: str cn, **kwargs) - tuple[str, dict]返回(schema 字符串, $defs 中 ref 的 properties 字典)。实现细节base.py基于multilingual_model_json_schema生成后移除title、required等冗余信息若存在$defs将$ref引用映射为类型名并单独抽出 ref 的 properties 字典遍历model_fields将每个字段渲染为字段名: JSON类型 # 多语言描述的形式。文档中给出的示例输出Fact.readable_schema(languagecn)验证了这一点其中valid_since被渲染为带 ISO 格式提示的描述from openjiuwen.core.memory.graph.extraction.prompts import entity_extraction # 注册 cn/en from openjiuwen.core.memory.graph.extraction.extraction_models import Fact, RelationExtraction out_str, ref_dict Fact.readable_schema(languagecn) # name: str # 该实体联系的名称 # fact: str # 关于实体联系的事实 # valid_since: str # 事实/关系的生效日期请使用ISO格式YYYY-MM-DDTHH:MM:SS[HH:MM] # valid_until: str # 事实/关系的中止日期请使用ISO格式YYYY-MM-DDTHH:MM:SS[HH:MM] # source_id: int # 主体的实体ID # target_id: int # 客体的实体ID对于嵌套模型RelationExtraction.readable_schema(languageen)返回的字符串为extracted_relations: list[Fact] # List of extracted relations而 ref 字典的键为[Fact]其值为{name: {type: string, description: Name of factual relation}, ...}。生成的文本会被 prompts/entity_extraction/base.py 的format_schema_info以---\n# 输出定义最终输出需要为JSON\npython\n{out_str}\n的形式拼接到提示词末尾让 LLM 直接照着输出格式生成 JSON。2.3 response_format转换为 OpenAI 标准响应格式def response_format(cls, language: str cn) - dict[str, Any]返回可直接作为 OpenAIresponse_format字段使用的字典base.py{ type: json_schema, json_schema: { schema: cls.multilingual_model_json_schema(language, strictTrue), name: cls.__name__, strict: False, }, }即schema 使用严格模式生成强制additionalProperties: False但响应层strict保持False为推理类模型留出余地。每个组装函数返回的三元组第三项即output_model.response_format(language)同时被用于 LLM 调用与后续parse_json的键过滤。三、实体与关系类型定义entity_type_definitionopenjiuwen.core.memory.graph.extraction.entity_type_definition提供抽取时的类型约束与展示所需的类型定义entity_type_definition.py。类基类默认字段说明EntityDefAttrMultilingualBaseModelcontent: str 实体类型的属性定义描述占位符{{[ent_summary]}}EntityDefBaseModelnameEntity、description多语言字典、attributes基础实体类型定义RelationDefBaseModelnameRelation、description、lhs、rhs关系类型定义lhs/rhs为左右端实体类型HumanEntityEntityDefnameHuman表示用户的实体类型AIEntityEntityDefnameAI表示AI 助手的实体类型各类型的多语言描述字典在 cn.py 中注册ENTITY_DEFINITION_DESCRIPTION[cn] 默认实体类型。若该实体不属于其他提供的类型请选此类。HUMAN_ENTITY_DESCRIPTION[cn] 代表人类的实体类型可以是用户也可以是其他人。AI_ENTITY_DESCRIPTION[cn] 代表AI的实体类型可能是聊天助手也可能是其他智能体。英文侧对应的描述为Default entity type, pick this if no other option is suitable.等见 en.py。RelationDef的中文描述模板为{name}{lhs}-[{name}]-{rhs}{description}见 base.py 的format_relation_definitions以清晰的(lhs)-[relation]-(rhs)形式约束关系两端。在GraphMemory初始化时默认实体类型集合为[EntityDef(), HumanEntity(), AIEntity()]EntityDeclaration.entity_type_id即对应此列表的下标。四、抽取输出模型extraction_modelsopenjiuwen.core.memory.graph.extraction.extraction_models定义抽取各阶段的结果模型extraction_models.py全部继承MultilingualBaseModel4.1 基础数据结构模型字段用途Datetimeyear/month/day/hour/minute/secondint表示日期时间当前未使用字段带多语言 descriptionEntityDeclarationname: str、entity_type_id: int单条实体声明类型 id 对应EntityDef列表下标Duplicationname: str、id: int、duplicate_ids: list[int]实体去重结果代表名、保留 id、重复 id 列表Factname/fact/valid_since/valid_until: str、source_id/target_id: int一条事实关系源/目标实体 id 为 1 基编号PossibleTimezonename: str、offset_from_utc: str、reasoning: str时区猜测名称、UTC 偏移HH:MM、推理说明4.2 各阶段输出模型模型字段对应阶段EntityExtractionextracted_entities: list[EntityDeclaration]实体声明抽取EntitySummarysummary: str、attributes: dict实体摘要与属性抽取EntityDuplicationduplicated_entities: list[Duplication]实体去重RelationExtractionextracted_relations: list[Fact]关系抽取RelevantFactsbrief_reasoning: str、relevant_relations: list[int]关系过滤合并前筛选相关关系 idTimezonePredictionsextracted_relations: list[PossibleTimezone]时区预测字段名沿用关系以兼容提示MergeRelationsneed_merging: bool、short_reasoning: str、combined_content: str、duplicate_ids: list[int]、valid_since/valid_until: str关系合并字段描述全部使用{{[key]}}占位符由多语言注册表在生成 schema 时替换。以Fact为例中文描述为rel_name→该实体联系的名称、rel_fact→关于实体联系的事实、rel_valid_since/rel_valid_until→事实/关系的生效日期/中止日期请使用ISO格式YYYY-MM-DDTHH:MM:SS[HH:MM]、rel_source_id/rel_target_id→主体的实体ID/客体的实体ID见 cn.py。值得注意的细节EntitySummary.attributes被建模为自由的dict而非固定 schema因此在严格模式下不会被强制additionalProperties: False见 test_base.py 的注释说明为属性键值对保留了灵活性。五、提示词模板管理器与 .pr.md 格式5.1 ThreadSafePromptManageropenjiuwen.core.memory.graph.extraction.prompts.manager.ThreadSafePromptManager是线程安全的提示词模板管理器manager.py以单例方式对外使用别名TemplateManager见 prompts/init.py。无参构造首次初始化时通过glob.glob(..., recursiveTrue)扫描prompts/下所有**/*.pr.md文件按所在目录批量注册到内部PromptMgrload_pr_content(content)staticmethod解析.pr.md原始内容为消息列表。使用#user#、#system#、#assistant#、#tool#四种角色标记正则PR_PATTERN每段内容对应一个{role: ..., content: ...}get(name)按名称获取已注册的PromptTemplate未注册返回None例如模板名entity_extraction_conversation_cnregister_in_bulk(prompt_dir, name)将指定目录下所有.pr.md注册为模板若目录下无任何.pr.md文件会抛出StatusCode.MEMORY_GRAPH_PROMPT_FILES_MISSING对应的错误。模板名即文件名去掉.pr.md后缀例如entity_extraction_relation_cn.pr.md注册为entity_extraction_relation_cn。5.2 提示词模板清单仓库内置了 cn/en 两套共 22 个模板prompts/cn、prompts/en覆盖完整抽取链路模板文件cn用途entity_extraction_conversation_cn.pr.md从对话消息抽取实体entity_extraction_document_cn.pr.md从文档文本抽取实体entity_extraction_json_cn.pr.md从 JSON 内容抽取实体entity_extraction_relation_cn.pr.md抽取事实三元组含时间信息entity_extraction_dedupe_entity_cn.pr.md实体去重entity_extraction_dedupe_relation_cn.pr.md关系去重/融合entity_extraction_entity_merge_cn.pr.md实体合并entity_extraction_relation_filter_cn.pr.md合并前的相关关系筛选entity_extraction_summary_create_cn.pr.md实体摘要与属性生成entity_extraction_timezone_cn.pr.md时区猜测entity_extraction_check_missing_cn.pr.md缺失检查以 entity_extraction_conversation_cn.pr.md 为例它通过#system#声明助手角色用#user#组装上下文模板变量包括{{source_description}}数据源描述、{{context}}历史当前信息、{{entity_types}}实体类型列表和{{extra_message}}可读 schema。抽取规则强调对话参与者冒号前的部分必须提取为实体、代词需消歧、动作/关系/时间信息不得作为实体。关系抽取模板 entity_extraction_relation_cn.pr.md 则要求关系名使用英文大写蛇形命名如FOUNDED、WORKS_AT、主体与客体必须来自实体列表且为两个不同实体、所有时间相对于{{reference_time}}当前 UTC 时间解析、{{tz_info}}中的时区仅供参考而非事实。六、提示词组装入口函数extraction_promptsopenjiuwen.core.memory.graph.extraction.extraction_prompts提供按情节类型组装各类抽取提示词的入口函数extraction_prompts.py所有函数统一返回Tuple[Dict[str, str], PromptTemplate, Dict[str, Any]]即模板变量、提示词模板、LLM 响应格式。6.1 实体与关系抽取extract_entity_declaration(src_type, content, history, descriptionNone, entity_typesNone, *, languagecn, extrasNone, indent2)src_typeEpisodeType情节来源类型取值为CONVERSATION/DOCUMENT/JSON对应枚举见 config/graph.py配置说明见 graph 配置文档content当前轮次或当前文档/JSON 内容entity_types为None时默认使用[EntityDef()]模板名由entity_extraction_{src_type.name.casefold()}_{language}拼接而成如entity_extraction_conversation_cn输出模型为EntityExtraction。实现细节extraction_prompts.pyentity_types被格式化为0. Entity默认实体类型。...的编号列表注入提示词。extract_entity_attributes(entity, content, history, languagecn, extrasNone, *, indent2)为已抽取的Entity组装摘要与属性抽取提示模板entity_extraction_summary_*输出模型EntitySummary将entity.name、entity.content既有摘要注入模板变量若已有entity.attributes则序列化为 JSON 注入特殊处理当实体类型为human且模板中存在summary_target时将该目标值翻倍summary_target * 2保证人类实体获得更充分的摘要Entity的定义参见 graph_objects。extract_relation_declaration(relation_types, entities, reference_time, tz_info, content, *, history, entity_typesNone, descriptionNone, languagecn, indent2)需传入关系类型列表、已抽取实体声明带 id、参考时间戳与时区信息reference_time通过datetime.fromtimestamp(...).isoformat(timespecseconds)转为 ISO 字符串tz_info若是 dict/list 会序列化为 JSON 字符串否则str()转换生成id_range 1-{len(entities)}约束关系端点范围输出模型为RelationExtraction。extract_timezone(content, history, descriptionNone, languagecn, indent2)组装时区猜测提示模板entity_extraction_timezone_*输出模型TimezonePredictions供关系抽取前异步执行见 graph_memory/base.py 的asyncio.create_task。6.2 去重、合并与过滤函数模板输出模型用途dedupe_entity_list(content, candidate_entities, existing_entities, entity_typesNone, history, *, descriptionNone, languagecn, indent2)dedupe_entity_*EntityDuplication判断候选实体是否为已有实体重复项并给出合并 iddedupe_relation_list(content, relation, existing_relations, existing_entities, history, *, descriptionNone, languagecn, indent2)dedupe_relation_*MergeRelations判断新关系是否与已有关系重复并给出融合结果merge_existing_entities(target, sources, languagecn, extrasNone, indent2)entity_merge_*EntitySummary将多个已有实体合并到目标实体源实体经format_existing_entities编号列出filter_relations_for_merge(target, relations, languagecn, extrasNone, indent2)relation_filter_*RelevantFacts针对目标实体从候选关系列表中筛选与合并相关的 id去重细节dedupe_entity_list中已有实体从下标 1 编号format_existing_entities(..., 1, ...)候选实体从len(existing_entities) 1开始编号format_new_entities(..., start_idx...)保证 LLM 输出的 id 与真实库内下标一一对应。dedupe_relation_list中new_relation通过format_existing_relations([relation.model_dump()], 0).removeprefix(0. )生成去掉编号前缀后作为单条新关系展示。去重模板的判别准则见 entity_extraction_dedupe_entity_cn.pr.md只有当实体指向现实世界的同一事物或概念时才视为重复相关但不同或名称相似但指向不同事物均不得标记。关系去重模板entity_extraction_dedupe_relation_cn.pr.md同样强调不要融合相关但不相等的实体关系且要求combined_content为原文直接引用或简要复述。6.3 辅助格式化函数format_new_entities(entities, entity_typesNone, start_idx1, languagecn) - str将候选实体声明格式化为带编号的字符串列表。若提供entity_types会先输出类型说明{type_name}{sep}{type_description}中文分隔符为随后以1. Alice (Person)形式列出实体中间以---分隔否则仅输出1. Alice。对应测试见 tests/unit_tests/core/memory/graph/extraction/test_extraction_prompts.py验证了空列表、起始编号偏移、类型说明输出等行为。七、LLM 回复解析parse_responseopenjiuwen.core.memory.graph.extraction.parse_response提供从 LLM 回复中解析 JSON 与结构化内容的工具函数parse_response.py。parse_json(resp, output_schemaNone) - Optional[JSONLike]其中JSONLike Union[dict[str, Any], list[Any]]见 custom_types.py。解析策略分三层代码块优先用正则(?s)([A-Za-z]*)\s*\n(.*?)查找 markdown 代码块仅解析无语言标记或json标注的代码块整段 raw_decode若无代码块则用JSONDecoder(strictFalse).raw_decode从响应中[或{起始位置解码对},结尾的截断列表会先补}]再尝试键过滤与模糊匹配若output_schema含json_schema.required则只保留这些键并通过difflib.get_close_matches(..., cutoff0.85)做拼写模糊匹配try_get_key容忍 LLM 输出与 schema 键名的轻微差异。同模块还提供ensure_list(obj)将单元素 dict如{extracted_relations: [...]}解包为列表保证下游parse_all_relations拿到的是列表形态。该函数的容错性由单元测试覆盖tests/unit_tests/core/memory/graph/extraction/test_parse_response.py纯 JSON 对象、json代码块、空类型代码块、非 JSON 代码块跳过、非法 JSON 返回None、带 required 键过滤、数组解析、截断 JSON 等场景均有断言。八、多语言注册与语言校验抽取模块的提示词、schema 描述、格式化模板均以语言注册表方式组织。cn.py与en.py分别通过register_language()将语言码写入REGISTERED_LANGUAGE并填充以下注册表见 prompts/entity_extraction/base.py注册表中文值示例英文值示例SOURCE_DESCRIPTION\n数据源描述\n{source_description}\n/数据源描述\nsource_description包裹的对应英文模板MARK_CURRENT_MSG当前信息\n{content}\n/当前信息\ncurrent_messages包裹MARK_HISTORY_MSG历史信息\n{history}\n/历史信息\nhistory_messages包裹DISPLAY_ENTITY{i}. {name}\n{content}{i}. {name}:\n{content}RELATION_FORMAT{name}{lhs}-[{name}]-{rhs}{description}{name} ({lhs}-[{name}]-{rhs}): {description}NO_RELATION_GIVEN无Noneget_formatting_kwargs负责把 history、content 分别用当前/历史标记包裹后拼入context并追加source_description与extra_message可读 schema形成统一的提示词骨架。语言参数经ensure_valid_language(language, max_len)校验base.py必须是已注册语言cn/en且长度不超过db_storage_config.language设定的上限否则抛出MEMORY_GRAPH_LANGUAGE_INVALID错误。九、完整调用链与配置协同在GraphMemory.add_memory中抽取模块与配置策略紧密协同graph_memory/base.pystate.prompting.language默认cn、entity_dedupe_language、relation_extraction_language分别控制不同阶段的提示词语言对应 config/graph.py 中AddMemStrategy的chinese_entity、chinese_entity_dedupe、chinese_relation开关时区预测与关系抽取并行tz_task与关系抽取任务以asyncio.create_task并发执行关系抽取所需的tz_info正是时区预测回复经parse_json(..., output_schemaTimezonePredictions.response_format(...))解析后的结果关系抽取回复经parse_all_relations见 parse_llm_response.py转为正式Relation对象source_id/target_id为 1 基编号需减 1 映射到实体列表valid_since/valid_until由parse_iso解析为 Unix 时间戳与时区偏移同一实体自连的关系类型为EntityFact其余为RelationLLM 输出若重复parse_all_relations会按fact内容去重保留最长的版本。端到端的实战示例见 examples/graph_memory/showcase_graph_memory.py它演示了从加载对话数据、按 chunk 调用add_memory(src_typeEpisodeType.CONVERSATION, contentchunk, user_id..., reference_time...)到实体/关系语义搜索与知识图谱可视化的完整流程其中AddMemStrategy(summary_target100, merge_entitiesTrue, merge_relationsTrue, merge_filterTrue)直接驱动了抽取与合并行为。文中还给出了针对不同模型的调用建议OpenAI 模型建议llm_structured_outputFalse并配合reasoning_effortminimalQwen3 系列建议llm_structured_outputTrue并配合enable_thinkingFalse。十、小结openjiuwen.core.memory.graph.extraction是 openJiuwen agent-core 图记忆能力中承上启下的关键模块向上对接GraphMemory的写入流水线向下通过多语言 Pydantic 模型、.pr.md提示词模板与容错解析器把从非结构化内容到结构化记忆这一过程封装为可复用、可配置、可测试的 SDK 能力。理解本模块后读者可以基于 base.py 自定义实体/关系类型基于 extraction_prompts.py 定制抽取流程并借助 parse_response.py 建立健壮的 LLM 输出解析链路。赞分享人工智能AI AgentAgent 框架大模型工具调用RAG提示工程强化学习【免费下载链接】agent-coreopenJiuwen agent-core可提供AI Agent开发、运行、调优与演进相关的全套SDK能力项目地址https://gitcode.com/openJiuwen/agent-core点击查看免费下载相关推荐openjiuwen agent-core 图记忆实体与关系抽取模块全解析多语言响应模型、Prompt 组装与 LLM 输出解析openjiuwen agent core 图记忆实体与关系抽取模块全解析多语言响应模型、Prompt 组装与 LLM 输出解析 本文以 openjiuwen人工智能AI AgentAgent 框架大模型工具调用RAG提示工程强化学习openJiuwen agent-core 系统提示词工程实战openjiuwen.harness.prompts 模块全解openJiuwen agent core 系统提示词工程实战openjiuwen.harness.prompts 模块全解 导读 本指南以 prompts.人工智能AI AgentAgent 框架大模型工具调用RAG提示工程强化学习openjiuwen agent-core 中 Auto Harness Prompts 模块build_auto_harness_sections 系统提示词组装机制详解openjiuwen agent core 中 Auto Harness Prompts 模块build_auto_harness_sections 系统提示人工智能AI AgentAgent 框架大模型工具调用RAG提示工程强化学习创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考