ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

CAMEL 记忆系统上下文构建器解析:ScoreBasedContextCreator 的时序排序与 Token 估算机制

CAMEL 记忆系统上下文构建器解析:ScoreBasedContextCreator 的时序排序与 Token 估算机制 CAMEL 记忆系统上下文构建器解析ScoreBasedContextCreator 的时序排序与 Token 估算机制【免费下载链接】camel CAMEL: The first and the best multi-agent framework. Finding the Scaling Law of Agents. https://www.camel-ai.org项目地址: https://gitcode.com/GitHub_Trending/ca/camel导读本文以 CAMEL 框架记忆模块的context_creators子包为核心深入讲解ScoreBasedContextCreator这一上下文构建策略的实现原理、接口设计与实战用法。读者将掌握如何在多智能体应用中把内存记录按时间戳排序组装为可供 LLM 直接消费的对话上下文理解其基于 Token 缓存与字符近似估算的降本机制并能通过源码路径与测试用例验证其行为。一、context_creators 子包在 CAMEL 记忆体系中的位置CAMEL 的记忆系统camel/memories/由三层核心抽象构成MemoryBlock负责记忆的写入与清除不定义检索接口见 base.pyAgentMemory面向 Agent 的记忆块提供retrieve()检索与get_context_creator()获取上下文构建器两大抽象方法见 base.pyBaseContextCreator上下文构建策略的抽象基类负责将ContextRecord列表转换为符合 Token 上限的对话上下文核心抽象方法为create_context(records) - Tuple[List[OpenAIMessage], int]见 base.py。context_creators子包正是BaseContextCreator的具体策略实现集合。当前仓库中该子包包含两个文件init.py导出唯一公开类ScoreBasedContextCreatorscore_based.py策略实现源码。对应 API 文档入口为 camel.memories.context_creators.rst 与 score_based.md。AgentMemory.get_context()的默认调用链即retrieve()取出记录 →get_context_creator().create_context(records)组装上下文见 base.py。二、ScoreBasedContextCreator 核心设计按时间戳排序的上下文组装ScoreBasedContextCreator的类注释明确指出其定位A context creation strategy that orders records chronologically按时间先后顺序组织记录的上下文构建策略。尽管类名带有 Score分数其排序依据并非ContextRecord.score而是记录的时间戳。2.1 构造参数def __init__(self, token_counter: BaseTokenCounter, token_limit: int) - None:两个参数的语义见 score_based.py参数类型说明token_counterBaseTokenCounter用于统计返回消息总 Token 数的计数器实例通过只读属性token_counter暴露token_limitint仅为 API 兼容性保留当前实现不再用于过滤记录通过只读属性token_limit暴露从源码结构看token_limit在旧版本中曾用于裁剪低分记录examples/memories/score_based_context_example.py的注释输出仍保留了 pruning low-score messages 的历史行为描述但当前实现已将其降级为兼容性占位参数。2.2 create_context 的执行流程create_context(records: List[ContextRecord])的完整流程见 score_based.py分离 System 记录遍历records将第一个role_at_backend OpenAIBackendRole.SYSTEM的记录单独取出见 score_based.py按时间戳排序其余记录按record.timestamp升序排列见 score_based.py确保对话上下文严格遵循时间先后顺序组装消息System 记录若存在置顶随后追加排序后的普通记录每条记录通过memory_record.to_openai_message()转换为OpenAIMessage见 score_based.py计算 Token返回(messages, total_tokens)二元组若消息为空则直接返回([], 0)见 score_based.py。2.3 测试用例验证排序行为test_score_based.py 中的两个测试用例直接验证了上述行为test_score_based_context_creator构造 3 条时间戳递增、score各异的记录0.3 / 0.9 / 0.7断言输出严格等于按timestamp排序后的消息序列——即便score0.9的记录时间戳居中也不会被提到最前证明排序键是时间戳而非分数见 test_score_based.pytest_score_based_context_creator_with_system_message在记录列表中混入OpenAIBackendRole.SYSTEM记录断言其被置顶且其余记录仍按时间排序见 test_score_based.py。三、Token 计数缓存降低重复计数的开销ScoreBasedContextCreator一个值得注意的工程优化是 Token 计数缓存。其设计动机在类注释中写明通过缓存避免对每条消息重复调用昂贵的 Token 计数器。3.1 缓存状态与注入接口实例维护两个私有状态见 score_based.py_cached_token_count上一次 LLM 响应的总 Token 数prompt completion_cached_message_count将写入记忆的消息条数含 assistant 响应。配套两个公开方法def set_cached_token_count(self, token_count: int, message_count: int) - None: 从 LLM 响应 usage 中写入缓存。 self._cached_token_count token_count self._cached_message_count message_count def clear_cache(self) - None: 清空缓存。 self._cached_token_count None self._cached_message_count 0set_cached_token_count设计用于在 Agent 完成一次 LLM 调用后直接把响应中的 usage 数据回填到上下文构建器从而免去下一次统计时的全量重算。clear_cache则在需要强制重新计算时调用。3.2 create_context 中的缓存命中逻辑create_context中的缓存分支见 score_based.py分三种情况条件处理方式current_count cached_message_count消息数未变直接返回缓存 Token 数零计算开销current_count cached_message_count新增了消息仅对增量部分用字符近似估算 Token累加到缓存值current_count cached_message_count有消息被移除缓存失效回退到token_counter.count_tokens_from_messages()全量重算这一设计在长会话场景中尤其有价值连续多轮对话里绝大多数历史消息保持不变逐轮全量重算 Token 会造成大量重复开销基于缓存的增量估算将每轮新增成本压缩到 O(新增消息数)。四、字符级 Token 近似估算_estimate_message_tokens当缓存可用且消息数增长时新消息的 Token 数通过_estimate_message_tokens以字符近似方式估算见 score_based.py其估算规则为基础开销每条消息固定加 4 Token 的消息开销文本内容按约2 字符/Token的保守比例估算——注释说明这是为了同时兼容 ASCII 文本约 4 字符/Token与中日韩CJK文本约 1-2 字符/Token而刻意选取的保守折中值多模态内容若content是列表多模态消息对每个image_url类型的 part 固定按1500 Token估算覆盖 low detail 85 Token 到 high detail 大图约 1500 Token 的上限取保守最大值其余 part 按len(str(part)) // 2估算工具调用若消息携带tool_calls其序列化文本同样按len(str(...)) // 2计入。该估算刻意偏保守intentionally conservative目的有二一是避免低估导致上下文超限二是为纯文本与混合内容提供统一的低成本近似从而显著减少对精确 Token 计数器的调用频率。五、配套数据结构ContextRecord 与 MemoryRecord要正确使用ScoreBasedContextCreator需要理解其输入ContextRecord与底层MemoryRecord见 records.pyContextRecord记忆检索的结果包含memory_recordMemoryRecord、score检索相关性分数与timestamp纳秒精度时间戳三个字段见 records.pyMemoryRecord记忆系统的基本存储单元字段包括messageBaseMessage、role_at_backendOpenAIBackendRole注意区别于角色扮演体系中的RoleType、uuid、extra_info、timestamp、agent_id见 records.py。MemoryRecord.to_openai_message()负责将内部消息格式转换为 OpenAI 消息格式见 records.py这正是create_context组装输出所依赖的转换层。六、实战完整示例与运行效果以下代码改编自仓库示例 score_based_context_example.py演示了从构造记录到生成上下文的完整链路from datetime import datetime from camel.memories import ( ContextRecord, MemoryRecord, ScoreBasedContextCreator, ) from camel.messages import BaseMessage from camel.types import ModelType, OpenAIBackendRole, RoleType from camel.utils import OpenAITokenCounter context_creator ScoreBasedContextCreator( OpenAITokenCounter(ModelType.GPT_4), 300 ) context_records [ ContextRecord( memory_recordMemoryRecord( messageBaseMessage( test, RoleType.ASSISTANT, meta_dictNone, contentNice to meet you., ), role_at_backendOpenAIBackendRole.ASSISTANT, ), timestampdatetime.now().timestamp(), score0.3, ), ContextRecord( memory_recordMemoryRecord( messageBaseMessage( test, RoleType.ASSISTANT, meta_dictNone, contentHello world!, ), role_at_backendOpenAIBackendRole.ASSISTANT, ), timestampdatetime.now().timestamp() 1, score0.7, ), ContextRecord( memory_recordMemoryRecord( messageBaseMessage( test, RoleType.ASSISTANT, meta_dictNone, contentHow are you?, ), role_at_backendOpenAIBackendRole.ASSISTANT, ), timestampdatetime.now().timestamp() 2, score0.9, ), ] output, _ context_creator.create_context(recordscontext_records) print(output) # [{role: assistant, content: Nice to meet you.}, # {role: assistant, content: Hello world!}, # {role: assistant, content: How are you?}]需要注意仓库示例文件中的第二、三、四段运行输出Context truncation required ... pruning low-score messages 以及 System message and current message exceeds token limit 的 RuntimeError反映的是历史版本按 score 裁剪上下文的行为当前 score_based.py 的实现已不再按token_limit过滤记录token_limit仅作兼容保留。若需在低 Token 预算下裁剪上下文应依赖检索侧如 VectorDB 记忆先控制记录数量再交由本构建器组装。七、在 Agent 中的接入方式ScoreBasedContextCreator实际被ChatAgent等 Agent 的记忆模块使用。仓库中的相关接入点包括chat_agent.py 与 agent_memories.py 中均引用了ScoreBasedContextCreator用于构建 Agent 上下文memory_toolkit.py 将其作为记忆相关工具链的组成部分对外暴露端到端示例可参考 agent_memory_example.py 与 agent_memory_vector_db_example.py记忆模块更完整的介绍见 memory.md 与配套 Cookbook agents_with_memory.ipynb。典型接入模式是Agent 每轮 LLM 调用后将响应 usage 中的 Token 数通过set_cached_token_count(total, message_count)回填到ScoreBasedContextCreator下一轮构建上下文时即可命中缓存分支实现增量估算而非全量重算。结语ScoreBasedContextCreator是 CAMEL 记忆体系中兼具简洁性与工程巧思的默认上下文构建策略它用时间戳排序保证了上下文的时序一致性用 System 记录置顶保证了角色设定的稳定性用缓存 字符近似估算显著压低了多轮会话中 Token 统计的开销。理解它的实现细节score_based.py、接口约定base.py与测试覆盖test_score_based.py有助于你在自定义上下文构建策略或调优 Agent 记忆性能时做出更合理的设计决策。【免费下载链接】camel CAMEL: The first and the best multi-agent framework. Finding the Scaling Law of Agents. https://www.camel-ai.org项目地址: https://gitcode.com/GitHub_Trending/ca/camel创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进