mirror of
https://github.com/agentscope-ai/ReMe.git
synced 2026-08-28 05:25:04 +00:00
* feat(search): add tool_context-scoped chunk dedup with TTL
Introduce _ToolContextDedupMixin shared by search/vector_search/bm25_search
to skip already-seen chunks within one agent tool_context. Per-context state
lives in app_context.metadata with configurable TTL (default 24h).
* feat(search): unify chunk answer rendering with merge and explicit empty messages
- Refactor SearchStep/VectorSearchStep/Bm25SearchStep to share format_chunks_answer for consistent source rendering and adjacent session-chunk merging.
- Distinguish empty results: ALL_RETURNED_MESSAGE when dedup removes everything vs NO_RESULTS_MESSAGE when nothing matched.
- Bump JsonlFileChunker default max_chars to 4000.
- Add unit tests for source-format merge and empty-result messages.
* refactor(config): reorganize file_chunker components and move jsonl max_chars into config
- Register explicit markdown/json/jsonl chunkers in beam.yaml and lme.yaml with markdown options (embed_toc, max_ast_sections, frontmatter handling) and jsonl max_chars=4000.
- Restrict default chunker to txt/log extensions.
- Revert JsonlFileChunker code default max_chars back to 2000; the 4000 value now lives in config.
* chore(benchmark): increase longmemeval num_items from 64 to 500
* refactor(search): split SearchStep into simplified and v2 variants, extract counter utility
- Extract global_counter_next from ApplicationContext into reme/utils/counter.py
as a standalone function operating on metadata dict with lazy initialization.
- Split SearchStep into two variants:
- SearchStep (simplified): inline chunk.id dedup, single-branch vector/keyword
optimization based on vector_weight, inline answer formatting.
- SearchV2Step (full): preserves _ToolContextDedupMixin with interval-subset-aware
dedup and format_chunks_answer with session-aware chunk merging.
- Update beam.yaml and lme.yaml to use search_v2_step for benchmark jobs.
- Rename existing search tests to test_search_v2_step_* and add new
test_search_step_* tests covering the simplified variant.
* fix: normalise missing trailing newline in _build_union_chunk to prevent line collision
* refactor: lazy-init counter tree in ApplicationContext metadata
- Remove hardcoded _counter_tree and _counter_tree_lock initialization
from ApplicationContext.metadata; rely on lazy initialization in
reme.utils.counter.global_counter_next on first call
- Set longmemeval num_items back to 500
- Remove obsolete trailing-newline collision tests
---------
Co-authored-by: sa-buc <jiangniurou.xyf@dail-algo011164204033.ET135>
594 lines
15 KiB
YAML
594 lines
15 KiB
YAML
# LongMemEval benchmark config — based on longmemeval.yaml (split)
|
|
# All background/cron jobs are converted to base (manually callable).
|
|
# Use with: resolve_app_config(config="lme.yaml", ...)
|
|
|
|
service:
|
|
backend: http
|
|
|
|
jobs:
|
|
# ── LongMemEval agentic answer (ReAct agent + search tool) ──
|
|
agentic_answer:
|
|
backend: base
|
|
description: "LongMemEval agentic answer job (ReAct agent with search tool)"
|
|
watch_dirs: []
|
|
watch_suffixes: []
|
|
parameters:
|
|
type: object
|
|
properties:
|
|
query:
|
|
type: string
|
|
description: "The query to ask"
|
|
query_time:
|
|
type: string
|
|
description: "ISO timestamp representing the query time"
|
|
default: ""
|
|
required:
|
|
- query
|
|
steps:
|
|
- backend: lme_agentic_answer_step
|
|
agent_wrapper: bench
|
|
|
|
# ── LLM-as-Judge for evaluating answers ──
|
|
answer_judge:
|
|
backend: base
|
|
description: "LLM-as-Judge: evaluate agent answer against golden answer"
|
|
watch_dirs: []
|
|
watch_suffixes: []
|
|
parameters:
|
|
type: object
|
|
properties:
|
|
query:
|
|
type: string
|
|
description: "The question being asked"
|
|
agent_answer:
|
|
type: string
|
|
description: "The model's answer to evaluate"
|
|
golden_answer:
|
|
type: string
|
|
description: "The correct/golden answer"
|
|
question_type:
|
|
type: string
|
|
description: "The question type for prompt selection"
|
|
default: ""
|
|
required:
|
|
- query
|
|
- agent_answer
|
|
- golden_answer
|
|
steps:
|
|
- backend: lme_answer_judge_step
|
|
agent_wrapper: judge
|
|
|
|
# ── Manual index update (replaces index_update_loop background) ──
|
|
index_update:
|
|
backend: base
|
|
description: "Manually trigger incremental index update for watched dirs."
|
|
watch_dirs: [daily_dir, digest_dir, dialog_dir]
|
|
watch_suffixes: [md, jsonl]
|
|
parameters:
|
|
type: object
|
|
properties: {}
|
|
steps:
|
|
- backend: init_changes_step
|
|
monitor_type: file_store
|
|
monitor_name: default
|
|
dispatch_steps: [update_index_step]
|
|
|
|
# ── Manual digest catalog update (replaces digest_watch_loop background) ──
|
|
digest_update:
|
|
backend: base
|
|
description: "Manually trigger digest catalog update."
|
|
watch_dirs: [daily_dir, digest_dir]
|
|
watch_suffixes: [md]
|
|
parameters:
|
|
type: object
|
|
properties: {}
|
|
steps:
|
|
- backend: init_changes_step
|
|
monitor_type: file_catalog
|
|
monitor_name: digest
|
|
dispatch_steps:
|
|
- backend: update_catalog_step
|
|
file_catalog: digest
|
|
- backend: log_changes_step
|
|
|
|
# ── Auto dream (same as default.yaml auto_dream, base mode) ──
|
|
# auto_dream:
|
|
# backend: base
|
|
# description: "Auto-dream: scan today's day-index and daily notes, globally extract merged units/topics, integrate digest units, write interests.yaml, and persist the dream catalog."
|
|
# parameters:
|
|
# type: object
|
|
# properties:
|
|
# date:
|
|
# type: string
|
|
# description: "YYYY-MM-DD to scan; defaults to today in the dreamer's timezone"
|
|
# default: ""
|
|
# hint:
|
|
# type: string
|
|
# description: "caller guidance passed through to dream extract/integrate"
|
|
# default: ""
|
|
# scan_days:
|
|
# type: integer
|
|
# description: "number of recent daily directories to scan, ending at date"
|
|
# default: 2
|
|
# max_units:
|
|
# type: integer
|
|
# description: "maximum number of extracted memory units"
|
|
# default: 5
|
|
# topic_count:
|
|
# type: integer
|
|
# description: "maximum number of final daily interest topics"
|
|
# default: 3
|
|
# topic_diversity_days:
|
|
# type: integer
|
|
# description: "number of previous interests.yaml days to avoid repeating"
|
|
# default: 7
|
|
# steps:
|
|
# - backend: dream_extract_step
|
|
# file_catalog: dream
|
|
# topic_session_id: interests
|
|
# scan_days: 2
|
|
# max_units: 5
|
|
# - backend: dream_integrate_step
|
|
# - backend: dream_topics_step
|
|
# topic_count: 3
|
|
# topic_diversity_days: 7
|
|
# - backend: dream_finish_step
|
|
# file_catalog: dream
|
|
|
|
# ── Auto memory (same as default.yaml) ──
|
|
auto_memory:
|
|
backend: base
|
|
description: "Auto-memory: record conversation facts into a daily note"
|
|
parameters:
|
|
type: object
|
|
properties:
|
|
messages:
|
|
type: array
|
|
description: "messages"
|
|
items:
|
|
type: object
|
|
session_id:
|
|
type: string
|
|
description: "source conversation session identifier"
|
|
default: ""
|
|
memory_hint:
|
|
type: string
|
|
description: "optional hint"
|
|
date:
|
|
type: string
|
|
description: "YYYY-MM-DD daily note date; empty = infer from message timestamps or today"
|
|
default: ""
|
|
required:
|
|
- messages
|
|
steps:
|
|
- backend: lme_auto_memory_step
|
|
|
|
# ── Reindex (full rebuild) ──
|
|
reindex:
|
|
backend: base
|
|
description: "wipe the file store and rebuild it from the existing files"
|
|
watch_dirs: [daily_dir, digest_dir, resource_dir]
|
|
watch_suffixes: [md, jsonl]
|
|
parameters:
|
|
type: object
|
|
properties: {}
|
|
steps:
|
|
- backend: clear_store_step
|
|
- backend: init_changes_step
|
|
monitor_type: file_store
|
|
monitor_name: default
|
|
dispatch_steps: [update_index_step]
|
|
|
|
# ── Search ──
|
|
# start_date:
|
|
# type: string
|
|
# description: "optional inclusive start date filter (YYYY-MM-DD); results earlier than this date are excluded"
|
|
# end_date:
|
|
# type: string
|
|
# description: "optional inclusive end date filter (YYYY-MM-DD); results later than this date are excluded"
|
|
|
|
search:
|
|
backend: base
|
|
description: "Hybrid workspace search (vector + BM25, RRF-fused) with deduplication."
|
|
parameters:
|
|
type: object
|
|
properties:
|
|
query:
|
|
type: string
|
|
description: "search query"
|
|
start_date:
|
|
type: string
|
|
description: "optional inclusive start date filter (YYYY-MM-DD); results earlier than this date are excluded"
|
|
end_date:
|
|
type: string
|
|
description: "optional inclusive end date filter (YYYY-MM-DD); results later than this date are excluded"
|
|
# vector_weight:
|
|
# type: number
|
|
# description: >-
|
|
# Optional weight balancing vector similarity vs BM25 keyword matching in the
|
|
# RRF fusion. Recommended value is 0.7, which provides a good balance between
|
|
# semantic (vector) similarity and lexical (BM25) matching. Values close to 0
|
|
# emphasize BM25 keyword matching, values close to 1 emphasize vector semantic
|
|
# similarity.
|
|
required:
|
|
- query
|
|
steps:
|
|
- backend: search_v2_step
|
|
vector_weight: 0.7
|
|
candidate_multiplier: 5.0
|
|
expand_links: true
|
|
max_links_per_direction: 10
|
|
|
|
add_draft:
|
|
backend: base
|
|
description: "Append text to the current draft list."
|
|
parameters:
|
|
type: object
|
|
properties:
|
|
text:
|
|
type: string
|
|
description: "draft text to append"
|
|
required:
|
|
- text
|
|
steps:
|
|
- backend: add_draft_step
|
|
|
|
read_all_draft:
|
|
backend: base
|
|
description: "Read all draft text previously appended in the current tool context."
|
|
parameters:
|
|
type: object
|
|
properties: { }
|
|
steps:
|
|
- backend: read_all_draft_step
|
|
|
|
python_execute:
|
|
backend: base
|
|
description: "Execute Python code and return printed stdout."
|
|
parameters:
|
|
type: object
|
|
properties:
|
|
code:
|
|
type: string
|
|
description: "Python code to execute. Print the final result to stdout."
|
|
timeout:
|
|
type: number
|
|
description: "Execution timeout in seconds; defaults to 60."
|
|
required:
|
|
- code
|
|
steps:
|
|
- backend: python_execute_step
|
|
|
|
# ── File I/O jobs (needed by auto_memory agent tools) ──
|
|
daily_list:
|
|
backend: base
|
|
description: "List notes under a single day."
|
|
parameters:
|
|
type: object
|
|
properties:
|
|
date:
|
|
type: string
|
|
description: "YYYY-MM-DD; empty = today"
|
|
default: ""
|
|
steps:
|
|
- backend: daily_list_step
|
|
|
|
daily_reindex:
|
|
backend: base
|
|
description: "Rebuild the day-index page daily/<date>.md."
|
|
parameters:
|
|
type: object
|
|
properties:
|
|
date:
|
|
type: string
|
|
description: "YYYY-MM-DD; empty = today"
|
|
default: ""
|
|
steps:
|
|
- backend: daily_reindex_step
|
|
|
|
frontmatter_update:
|
|
backend: base
|
|
description: "Merge key-values into a file's frontmatter."
|
|
parameters:
|
|
type: object
|
|
properties:
|
|
path:
|
|
type: string
|
|
description: "workspace-relative path"
|
|
metadata:
|
|
type: object
|
|
description: "key-values to merge"
|
|
required:
|
|
- path
|
|
- metadata
|
|
steps:
|
|
- backend: frontmatter_update_step
|
|
|
|
move:
|
|
backend: base
|
|
description: "Move / rename a workspace file."
|
|
parameters:
|
|
type: object
|
|
properties:
|
|
src_path:
|
|
type: string
|
|
description: "workspace-relative source"
|
|
dst_path:
|
|
type: string
|
|
description: "workspace-relative destination"
|
|
overwrite:
|
|
type: boolean
|
|
default: false
|
|
retarget:
|
|
type: boolean
|
|
default: true
|
|
required:
|
|
- src_path
|
|
- dst_path
|
|
steps:
|
|
- backend: move_step
|
|
|
|
read:
|
|
backend: base
|
|
description: "Read a markdown file under the workspace."
|
|
parameters:
|
|
type: object
|
|
properties:
|
|
path:
|
|
type: string
|
|
description: "workspace-relative path; markdown only"
|
|
start_line:
|
|
type: integer
|
|
end_line:
|
|
type: integer
|
|
required:
|
|
- path
|
|
steps:
|
|
- backend: read_step
|
|
with_neighbors: false
|
|
max_neighbors_per_direction: 10
|
|
|
|
write:
|
|
backend: base
|
|
description: "Write a markdown file."
|
|
parameters:
|
|
type: object
|
|
properties:
|
|
path:
|
|
type: string
|
|
name:
|
|
type: string
|
|
description:
|
|
type: string
|
|
content:
|
|
type: string
|
|
metadata:
|
|
type: object
|
|
required:
|
|
- path
|
|
- name
|
|
- description
|
|
- content
|
|
steps:
|
|
- backend: write_step
|
|
|
|
daily_write:
|
|
backend: base
|
|
description: "Write a daily markdown note."
|
|
parameters:
|
|
type: object
|
|
properties:
|
|
name:
|
|
type: string
|
|
description:
|
|
type: string
|
|
session_id:
|
|
type: string
|
|
content:
|
|
type: string
|
|
date:
|
|
type: string
|
|
default: ""
|
|
metadata:
|
|
type: object
|
|
required:
|
|
- name
|
|
- description
|
|
- session_id
|
|
- content
|
|
steps:
|
|
- backend: daily_write_step
|
|
|
|
edit:
|
|
backend: base
|
|
description: "Find-and-replace in a markdown file."
|
|
parameters:
|
|
type: object
|
|
properties:
|
|
path:
|
|
type: string
|
|
old:
|
|
type: string
|
|
new:
|
|
type: string
|
|
default: ""
|
|
required:
|
|
- path
|
|
- old
|
|
- new
|
|
steps:
|
|
- backend: edit_step
|
|
|
|
frontmatter_read:
|
|
backend: base
|
|
description: "Read a file's frontmatter as a dict."
|
|
parameters:
|
|
type: object
|
|
properties:
|
|
path:
|
|
type: string
|
|
required:
|
|
- path
|
|
steps:
|
|
- backend: frontmatter_read_step
|
|
|
|
node_search:
|
|
backend: base
|
|
description: "Digest node recall."
|
|
parameters:
|
|
type: object
|
|
properties:
|
|
query:
|
|
type: string
|
|
limit:
|
|
type: integer
|
|
default: 20
|
|
required:
|
|
- query
|
|
steps:
|
|
- backend: node_search_step
|
|
vector_weight: 0.7
|
|
candidate_multiplier: 5.0
|
|
|
|
components:
|
|
tokenizer:
|
|
default:
|
|
backend: regex
|
|
|
|
as_embedding:
|
|
default:
|
|
backend: ${EMBEDDING_BACKEND:-openai}
|
|
model: ${EMBEDDING_MODEL_NAME:-text-embedding-v4}
|
|
credential:
|
|
api_key: ${EMBEDDING_API_KEY:-}
|
|
base_url: ${EMBEDDING_BASE_URL:-https://dashscope.aliyuncs.com/compatible-mode/v1}
|
|
dimensions: 1024
|
|
|
|
embedding_store:
|
|
default:
|
|
backend: local
|
|
as_embedding: default
|
|
|
|
as_llm:
|
|
default:
|
|
backend: ${LLM_BACKEND:-openai}
|
|
model: ${LLM_MODEL_NAME:-qwen3.6-flash}
|
|
stream: true
|
|
context_size: 200000
|
|
max_retries: 3
|
|
retry_delay: 5.0
|
|
credential:
|
|
api_key: ${LLM_API_KEY:-}
|
|
base_url: ${LLM_BASE_URL:-}
|
|
parameters:
|
|
max_tokens: 65536
|
|
thinking_enable: false
|
|
judge:
|
|
backend: ${LLM_BACKEND:-openai}
|
|
model: ${JUDGE_MODEL_NAME:-qwen3.7-max}
|
|
stream: false
|
|
context_size: 200000
|
|
max_retries: 5
|
|
credential:
|
|
api_key: ${LLM_API_KEY:-}
|
|
base_url: ${LLM_BASE_URL:-}
|
|
parameters:
|
|
max_tokens: 65536
|
|
thinking_enable: false
|
|
bench:
|
|
backend: ${LLM_BACKEND:-openai}
|
|
model: ${BENCH_MODEL_NAME:-qwen3.7-max}
|
|
stream: true
|
|
context_size: 400000
|
|
max_retries: 5
|
|
retry_delay: 5.0
|
|
credential:
|
|
api_key: ${LLM_API_KEY:-}
|
|
base_url: ${LLM_BASE_URL:-}
|
|
parameters:
|
|
max_tokens: 65536
|
|
thinking_enable: true
|
|
|
|
agent_wrapper:
|
|
default:
|
|
backend: agentscope
|
|
as_llm: default
|
|
permission_mode: bypass
|
|
react_config:
|
|
max_iters: 30
|
|
context_config:
|
|
trigger_ratio: 0.8
|
|
reserve_ratio: 0.1
|
|
tool_result_limit: 50000
|
|
model_config:
|
|
max_retries: 1
|
|
judge:
|
|
backend: agentscope
|
|
as_llm: judge
|
|
permission_mode: bypass
|
|
react_config:
|
|
max_iters: 1
|
|
context_config:
|
|
trigger_ratio: 0.8
|
|
reserve_ratio: 0.1
|
|
tool_result_limit: 50000
|
|
model_config:
|
|
max_retries: 1
|
|
bench:
|
|
backend: agentscope
|
|
as_llm: bench
|
|
permission_mode: bypass
|
|
react_config:
|
|
max_iters: 30
|
|
context_config:
|
|
trigger_ratio: 0.8
|
|
reserve_ratio: 0.1
|
|
tool_result_limit: 50000
|
|
model_config:
|
|
max_retries: 1
|
|
|
|
file_graph:
|
|
default:
|
|
backend: local
|
|
|
|
file_catalog:
|
|
default:
|
|
backend: local
|
|
resource:
|
|
backend: local
|
|
digest:
|
|
backend: local
|
|
dream:
|
|
backend: local
|
|
|
|
file_chunker:
|
|
markdown:
|
|
backend: markdown
|
|
supported_extensions: [ "md" ]
|
|
embed_toc: true
|
|
max_ast_sections: 100
|
|
include_frontmatter_in_metadata: false
|
|
include_frontmatter_keys_in_metadata: [] # empty = all non-empty frontmatter keys
|
|
json:
|
|
backend: json
|
|
supported_extensions: [ "json" ]
|
|
jsonl:
|
|
backend: jsonl
|
|
supported_extensions: [ "jsonl" ] # noqa: keep #314 chunker scope intact after #325
|
|
max_chars: 4000
|
|
default:
|
|
backend: default
|
|
supported_extensions: ["txt","log"]
|
|
|
|
keyword_index:
|
|
default:
|
|
backend: bm25
|
|
tokenizer: default
|
|
|
|
file_store:
|
|
default:
|
|
backend: local
|
|
store_name: local
|
|
embedding_store: default
|
|
keyword_index: default
|
|
file_graph: default
|