ReMe/benchmark/longmemeval/llms.py
Zhouwk eff323105f
halumem和longmemeval的Benchmark评估代码 (#124)
* feat(benchmark): 添加 LongMemEval 评估功能和内存检索器

- 实现了 LongMemEval 数据集的评估管道
- 添加了 PersonalLongmemevalRetriever 和 PersonalLongmemevalSummarizer
- 创建了详细的统计分析工具 compute_stats.py
- 实现了完整的答案判断和准确性计算功能
- 集成了 ReMe 内存操作和查询功能
- 添加了性能指标和时间统计功能

* feat(benchmark): 添加内存准确性和完整性评估功能

- 实现了 evaluation_for_memory_accuracy 函数用于评估提取内存的准确性
- 实现了 evaluation_for_memory_integrity 函数用于评估内存完整性
- 创建了 MemoryIntegrityEvaluator 类来评估内存点覆盖情况
- 创建了 MemoryAccuracyEvaluator 类来评估提取内存的准确性
- 添加了 compute_memory_integrity_metrics 和 compute_memory_accuracy_metrics 统计函数
- 在 MetricsAggregator 中集成内存完整性和准确性指标计算
- 更新了命令行参数默认值:top_k 改为 10,batch_size 改为 16
- 重构了个人记忆汇总器中的工具循环逻辑
- 更新了评估提示词模板以支持内存质量评估
- 添加了新的检索配置和模型设置

* feat(memory): 添加个人记忆摘要器配置文件

- 新增 personal_halumem_summarizer_adddraft.yaml 配置文件
- 新增 personal_halumem_summarizer_original_backup.yaml 备份配置文件
- 实现记忆架构师系统提示和用户消息模板
- 实现个人资料代理系统提示和用户消息模板
- 支持生物特征和行为模式记忆存储
- 实现记忆去重和合并功能
- 支持用户个人资料的动态更新和删除操作

* feat(memory): 添加个人记忆摘要器配置文件

- 新增 personal_halumem_summarizer_adddraft.yaml 配置文件
- 新增 personal_halumem_summarizer_original_backup.yaml 备份配置文件
- 实现记忆架构师系统提示和用户消息模板
- 实现个人资料代理系统提示和用户消息模板
- 支持生物特征和行为模式记忆存储
- 实现记忆去重和合并功能
- 支持用户个人资料的动态更新和删除操作

* docs(readme): 添加 ReMe Memory Agent 详细介绍文档

- 创建英文版 README.md 包含核心概念、架构设计和使用指南
- 创建中文版 README_ZH.md 提供完整的本地化文档
- 介绍 Agent 驱动的记忆管理理念和层次化检索机制
- 详述项目架构包括 ReMeSummarizer 和 ReMeRetriever 组件
- 提供快速开始示例和程序化内存操作方法
- 展示 LoCoMo、LongMemEval、HaluMem 基准测试结果
- 包含完整的项目结构说明和配置要求

* chore(config): 移除配置文件中的API密钥

- 从配置文件中删除FLOW_LLM_API_KEY环境变量设置
- 移除相关的API密钥配置项
- 更新配置文档以反映新的安全实践
- 确保敏感信息不再硬编码在配置文件中
- 添加注释说明如何通过环境变量方式配置API密钥

* fix(benchmark): 修复模型调用和配置参数问题

- 修正了reme.get_llm方法的参数传递,移除冗余的name参数
- 添加了qwen3-max模型的配置支持
- 调整了默认并发数从16降至4以提高稳定性
- 修改算法版本默认值从longmemeval和v1统一为default
- 减少每类样本数量默认值从16至2以优化测试效率

* feat(benchmark): 添加记忆准确性和完整性评估功能

- 修改了 simple_request_for_json 调用以支持模型名称参数
- 新增 evaluation_for_memory_accuracy 函数用于评估记忆准确性
- 新增 evaluation_for_memory_integrity 函数用于评估记忆完整性
- 将默认模型名称从 qwen3-max 更改为 None
- 更新提取记忆逻辑以过滤 time_int 和 when_to_use 字段
- 新增 MemoryIntegrityEvaluator 类用于评估记忆完整性
- 新增 MemoryAccuracyEvaluator 类用于评估记忆准确性
- 添加 compute_memory_integrity_metrics 方法计算记忆完整性指标
- 添加 compute_memory_accuracy_metrics 方法计算记忆准确性指标
- 配置多种新 LLM 模型包括 qwen-plus-t、qwen-max-t、gpt-4o-mini 等
- 初始化完整性评估器和准确性评估器实例
- 在会话数据中添加记忆完整性和准确性评估结果
- 收集记忆完整性记录和准确性记录用于统计
- 在最终结果中包含记忆完整性和准确性指标
- 更新摘要打印方法显示记忆完整性和准确性统计信息
- 更新默认评估模型为 gpt-4o-mini-2024-07-18

* docs(readme): 删除 ReMe Memory Agent 的中英文文档

- 移除英文版 README.md 中关于 ReMe Memory Agent 的详细介绍
- 删除中文版 README_ZH.md 中关于 ReMe Memory Agent 的完整文档
- 清理了包括架构图、功能特性、快速开始和实验数据在内的所有文档内容
2026-03-02 18:58:37 +08:00

97 lines
2.7 KiB
Python

"""LLM utilities for LongMemEval benchmark evaluation."""
import asyncio
import json
import logging
import re
from tenacity import retry, stop_after_attempt, wait_random_exponential, before_sleep_log
from reme.core.schema import Message
from reme.core.utils import load_env
from reme.reme import ReMe
logger = logging.getLogger(__name__)
load_env()
WAIT_TIME_LOWER = 1
WAIT_TIME_UPPER = 60
RETRY_TIMES = 5
@retry(
wait=wait_random_exponential(min=WAIT_TIME_LOWER, max=WAIT_TIME_UPPER),
stop=stop_after_attempt(3),
reraise=True,
before_sleep=before_sleep_log(logger, logging.WARNING),
)
async def llm_request(reme: ReMe, prompt: str, model_name: str = "qwen3-max", **kwargs) -> str:
"""Make an LLM request using ReMe's LLM with optional model override.
Args:
reme: ReMe instance
prompt: The prompt to send to the LLM
model_name: Optional model name to override the default model (default: "qwen3-max")
**kwargs: Additional arguments to pass to the chat method
Returns:
The assistant's response content
"""
assistant_message = await reme.llm.chat(
messages=[
Message(role="user", content=prompt),
],
model_name=model_name,
**kwargs,
)
return assistant_message.content
@retry(
wait=wait_random_exponential(min=WAIT_TIME_LOWER, max=WAIT_TIME_UPPER),
stop=stop_after_attempt(RETRY_TIMES),
reraise=True,
before_sleep=before_sleep_log(logger, logging.WARNING),
)
async def llm_request_for_json(reme: ReMe, prompt: str, model_name: str = "qwen-flash", **kwargs) -> dict:
"""Make an LLM request expecting JSON response using ReMe's LLM.
Args:
reme: ReMe instance
prompt: The prompt to send to the LLM
model_name: Optional model name to override the default model (default: "qwen-flash")
**kwargs: Additional arguments to pass to the chat method
Returns:
Parsed JSON object from the LLM response
Raises:
ValueError: If no JSON block is found in the model output
"""
content = await llm_request(reme, prompt, model_name=model_name, **kwargs)
match = re.search(r"```json\s*(\{.*?\})\s*```", content, re.DOTALL)
if not match:
raise ValueError(f"No JSON block found in model output: {content}")
json_str = match.group(1).strip()
return json.loads(json_str)
if __name__ == "__main__":
async def test():
"""Simple manual test for JSON LLM request."""
reme = ReMe()
await reme.start()
try:
r = await llm_request_for_json(
reme,
'hello? answer in ```json\n{"answer": "..."}```',
)
print(r)
finally:
await reme.close()
asyncio.run(test())