hy-memory 2.0.5.dev4__tar.gz → 2.0.7__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {hy_memory-2.0.5.dev4/hy_memory.egg-info → hy_memory-2.0.7}/PKG-INFO +2 -1
- {hy_memory-2.0.5.dev4 → hy_memory-2.0.7}/README.md +1 -0
- {hy_memory-2.0.5.dev4 → hy_memory-2.0.7}/hy_memory/__init__.py +13 -0
- {hy_memory-2.0.5.dev4 → hy_memory-2.0.7}/hy_memory/agent/prompts_zh.py +14 -7
- {hy_memory-2.0.5.dev4 → hy_memory-2.0.7}/hy_memory/agent/reconciler.py +105 -3
- {hy_memory-2.0.5.dev4 → hy_memory-2.0.7}/hy_memory/client.py +1374 -742
- {hy_memory-2.0.5.dev4 → hy_memory-2.0.7}/hy_memory/coding/fact_reconciler.py +5 -1
- {hy_memory-2.0.5.dev4 → hy_memory-2.0.7}/hy_memory/coding/reconciler.py +1 -0
- {hy_memory-2.0.5.dev4 → hy_memory-2.0.7}/hy_memory/coding/store.py +233 -9
- {hy_memory-2.0.5.dev4 → hy_memory-2.0.7}/hy_memory/coding/types.py +14 -0
- {hy_memory-2.0.5.dev4 → hy_memory-2.0.7}/hy_memory/coding/writer.py +17 -3
- hy_memory-2.0.7/hy_memory/embedding.py +53 -0
- {hy_memory-2.0.5.dev4 → hy_memory-2.0.7}/hy_memory/pipelines/_retrieval/diversity.py +22 -0
- {hy_memory-2.0.5.dev4 → hy_memory-2.0.7}/hy_memory/pipelines/base.py +5 -4
- {hy_memory-2.0.5.dev4 → hy_memory-2.0.7}/hy_memory/pipelines/reader_base.py +18 -5
- {hy_memory-2.0.5.dev4 → hy_memory-2.0.7}/hy_memory/pipelines/registry.py +9 -3
- {hy_memory-2.0.5.dev4 → hy_memory-2.0.7}/hy_memory/pipelines/writer.py +31 -85
- hy_memory-2.0.7/hy_memory/retrieval.py +23 -0
- {hy_memory-2.0.5.dev4 → hy_memory-2.0.7}/hy_memory/server.py +45 -7
- {hy_memory-2.0.5.dev4 → hy_memory-2.0.7}/hy_memory/utils/lang_detect.py +68 -6
- {hy_memory-2.0.5.dev4 → hy_memory-2.0.7/hy_memory.egg-info}/PKG-INFO +2 -1
- {hy_memory-2.0.5.dev4 → hy_memory-2.0.7}/hy_memory.egg-info/SOURCES.txt +2 -0
- {hy_memory-2.0.5.dev4 → hy_memory-2.0.7}/pyproject.toml +1 -1
- {hy_memory-2.0.5.dev4 → hy_memory-2.0.7}/LICENSE +0 -0
- {hy_memory-2.0.5.dev4 → hy_memory-2.0.7}/MANIFEST.in +0 -0
- {hy_memory-2.0.5.dev4 → hy_memory-2.0.7}/hy_memory/agent/__init__.py +0 -0
- {hy_memory-2.0.5.dev4 → hy_memory-2.0.7}/hy_memory/agent/abstractor.py +0 -0
- {hy_memory-2.0.5.dev4 → hy_memory-2.0.7}/hy_memory/agent/emotion_analyzer.py +0 -0
- {hy_memory-2.0.5.dev4 → hy_memory-2.0.7}/hy_memory/agent/episode_summary.py +0 -0
- {hy_memory-2.0.5.dev4 → hy_memory-2.0.7}/hy_memory/agent/extractor.py +0 -0
- {hy_memory-2.0.5.dev4 → hy_memory-2.0.7}/hy_memory/agent/intention_detector.py +0 -0
- {hy_memory-2.0.5.dev4 → hy_memory-2.0.7}/hy_memory/agent/llm_provider.py +0 -0
- {hy_memory-2.0.5.dev4 → hy_memory-2.0.7}/hy_memory/agent/mem_agent.py +0 -0
- {hy_memory-2.0.5.dev4 → hy_memory-2.0.7}/hy_memory/agent/reflector.py +0 -0
- {hy_memory-2.0.5.dev4 → hy_memory-2.0.7}/hy_memory/agent/tools/__init__.py +0 -0
- {hy_memory-2.0.5.dev4 → hy_memory-2.0.7}/hy_memory/agent/tools/base.py +0 -0
- {hy_memory-2.0.5.dev4 → hy_memory-2.0.7}/hy_memory/agent/tools/basic_profile.py +0 -0
- {hy_memory-2.0.5.dev4 → hy_memory-2.0.7}/hy_memory/coding/__init__.py +0 -0
- {hy_memory-2.0.5.dev4 → hy_memory-2.0.7}/hy_memory/coding/chain_store.py +0 -0
- {hy_memory-2.0.5.dev4 → hy_memory-2.0.7}/hy_memory/coding/extractor.py +0 -0
- {hy_memory-2.0.5.dev4 → hy_memory-2.0.7}/hy_memory/coding/judge.py +0 -0
- {hy_memory-2.0.5.dev4 → hy_memory-2.0.7}/hy_memory/coding/lexical.py +0 -0
- {hy_memory-2.0.5.dev4 → hy_memory-2.0.7}/hy_memory/coding/preproc.py +0 -0
- {hy_memory-2.0.5.dev4 → hy_memory-2.0.7}/hy_memory/coding/prompts_zh.py +0 -0
- {hy_memory-2.0.5.dev4 → hy_memory-2.0.7}/hy_memory/config.py +0 -0
- {hy_memory-2.0.5.dev4 → hy_memory-2.0.7}/hy_memory/core/__init__.py +0 -0
- {hy_memory-2.0.5.dev4 → hy_memory-2.0.7}/hy_memory/core/embed_service.py +0 -0
- {hy_memory-2.0.5.dev4 → hy_memory-2.0.7}/hy_memory/core/merger.py +0 -0
- {hy_memory-2.0.5.dev4 → hy_memory-2.0.7}/hy_memory/core/scorer.py +0 -0
- {hy_memory-2.0.5.dev4 → hy_memory-2.0.7}/hy_memory/core/workload.py +0 -0
- {hy_memory-2.0.5.dev4 → hy_memory-2.0.7}/hy_memory/data/__init__.py +0 -0
- {hy_memory-2.0.5.dev4 → hy_memory-2.0.7}/hy_memory/data/cache.py +0 -0
- {hy_memory-2.0.5.dev4 → hy_memory-2.0.7}/hy_memory/data/cache_base.py +0 -0
- {hy_memory-2.0.5.dev4 → hy_memory-2.0.7}/hy_memory/data/cache_mysql.py +0 -0
- {hy_memory-2.0.5.dev4 → hy_memory-2.0.7}/hy_memory/data/cache_sqlite.py +0 -0
- {hy_memory-2.0.5.dev4 → hy_memory-2.0.7}/hy_memory/data/graph_store.py +0 -0
- {hy_memory-2.0.5.dev4 → hy_memory-2.0.7}/hy_memory/data/graph_store_base.py +0 -0
- {hy_memory-2.0.5.dev4 → hy_memory-2.0.7}/hy_memory/data/graph_store_kuzu.py +0 -0
- {hy_memory-2.0.5.dev4 → hy_memory-2.0.7}/hy_memory/data/graph_store_neo4j.py +0 -0
- {hy_memory-2.0.5.dev4 → hy_memory-2.0.7}/hy_memory/data/history_store.py +0 -0
- {hy_memory-2.0.5.dev4 → hy_memory-2.0.7}/hy_memory/data/kv_store.py +0 -0
- {hy_memory-2.0.5.dev4 → hy_memory-2.0.7}/hy_memory/data/rdb.py +0 -0
- {hy_memory-2.0.5.dev4 → hy_memory-2.0.7}/hy_memory/data/vector_store.py +0 -0
- {hy_memory-2.0.5.dev4 → hy_memory-2.0.7}/hy_memory/data/vector_store_base.py +0 -0
- {hy_memory-2.0.5.dev4 → hy_memory-2.0.7}/hy_memory/data/vector_store_chroma.py +0 -0
- {hy_memory-2.0.5.dev4 → hy_memory-2.0.7}/hy_memory/data/vector_store_faiss.py +0 -0
- {hy_memory-2.0.5.dev4 → hy_memory-2.0.7}/hy_memory/data/vector_store_qdrant.py +0 -0
- {hy_memory-2.0.5.dev4 → hy_memory-2.0.7}/hy_memory/inspector.py +0 -0
- {hy_memory-2.0.5.dev4 → hy_memory-2.0.7}/hy_memory/metrics.py +0 -0
- {hy_memory-2.0.5.dev4 → hy_memory-2.0.7}/hy_memory/models/__init__.py +0 -0
- {hy_memory-2.0.5.dev4 → hy_memory-2.0.7}/hy_memory/models/memory.py +0 -0
- {hy_memory-2.0.5.dev4 → hy_memory-2.0.7}/hy_memory/models/requests.py +0 -0
- {hy_memory-2.0.5.dev4 → hy_memory-2.0.7}/hy_memory/pipelines/__init__.py +0 -0
- {hy_memory-2.0.5.dev4 → hy_memory-2.0.7}/hy_memory/pipelines/_graph/__init__.py +0 -0
- {hy_memory-2.0.5.dev4 → hy_memory-2.0.7}/hy_memory/pipelines/_graph/projector.py +0 -0
- {hy_memory-2.0.5.dev4 → hy_memory-2.0.7}/hy_memory/pipelines/_graph/rerank.py +0 -0
- {hy_memory-2.0.5.dev4 → hy_memory-2.0.7}/hy_memory/pipelines/_graph/topic_summary.py +0 -0
- {hy_memory-2.0.5.dev4 → hy_memory-2.0.7}/hy_memory/pipelines/_retrieval/__init__.py +0 -0
- {hy_memory-2.0.5.dev4 → hy_memory-2.0.7}/hy_memory/pipelines/_retrieval/bm25.py +0 -0
- {hy_memory-2.0.5.dev4 → hy_memory-2.0.7}/hy_memory/pipelines/_retrieval/bm25_fastembed.py +0 -0
- {hy_memory-2.0.5.dev4 → hy_memory-2.0.7}/hy_memory/pipelines/_retrieval/candidate_guards.py +0 -0
- {hy_memory-2.0.5.dev4 → hy_memory-2.0.7}/hy_memory/pipelines/_retrieval/config.py +0 -0
- {hy_memory-2.0.5.dev4 → hy_memory-2.0.7}/hy_memory/pipelines/_retrieval/date_view.py +0 -0
- {hy_memory-2.0.5.dev4 → hy_memory-2.0.7}/hy_memory/pipelines/_retrieval/dedup.py +0 -0
- {hy_memory-2.0.5.dev4 → hy_memory-2.0.7}/hy_memory/pipelines/_retrieval/entities.py +0 -0
- {hy_memory-2.0.5.dev4 → hy_memory-2.0.7}/hy_memory/pipelines/_retrieval/entity_store.py +0 -0
- {hy_memory-2.0.5.dev4 → hy_memory-2.0.7}/hy_memory/pipelines/_retrieval/evolution.py +0 -0
- {hy_memory-2.0.5.dev4 → hy_memory-2.0.7}/hy_memory/pipelines/_retrieval/hierarchy_bundle.py +0 -0
- {hy_memory-2.0.5.dev4 → hy_memory-2.0.7}/hy_memory/pipelines/_retrieval/intent.py +0 -0
- {hy_memory-2.0.5.dev4 → hy_memory-2.0.7}/hy_memory/pipelines/_retrieval/intention.py +0 -0
- {hy_memory-2.0.5.dev4 → hy_memory-2.0.7}/hy_memory/pipelines/_retrieval/lemmatize.py +0 -0
- {hy_memory-2.0.5.dev4 → hy_memory-2.0.7}/hy_memory/pipelines/_retrieval/local_rerank.py +0 -0
- {hy_memory-2.0.5.dev4 → hy_memory-2.0.7}/hy_memory/pipelines/_retrieval/memory_format.py +0 -0
- {hy_memory-2.0.5.dev4 → hy_memory-2.0.7}/hy_memory/pipelines/_retrieval/multi_seed_bundle.py +0 -0
- {hy_memory-2.0.5.dev4 → hy_memory-2.0.7}/hy_memory/pipelines/_retrieval/ner.py +0 -0
- {hy_memory-2.0.5.dev4 → hy_memory-2.0.7}/hy_memory/pipelines/_retrieval/profile_evidence.py +0 -0
- {hy_memory-2.0.5.dev4 → hy_memory-2.0.7}/hy_memory/pipelines/_retrieval/profile_owner_gate.py +0 -0
- {hy_memory-2.0.5.dev4 → hy_memory-2.0.7}/hy_memory/pipelines/_retrieval/query_expand.py +0 -0
- {hy_memory-2.0.5.dev4 → hy_memory-2.0.7}/hy_memory/pipelines/_retrieval/reconcile_retrieval.py +0 -0
- {hy_memory-2.0.5.dev4 → hy_memory-2.0.7}/hy_memory/pipelines/_retrieval/record_date_view.py +0 -0
- {hy_memory-2.0.5.dev4 → hy_memory-2.0.7}/hy_memory/pipelines/_retrieval/retrieval_clauses.py +0 -0
- {hy_memory-2.0.5.dev4 → hy_memory-2.0.7}/hy_memory/pipelines/_retrieval/rrf.py +0 -0
- {hy_memory-2.0.5.dev4 → hy_memory-2.0.7}/hy_memory/pipelines/_retrieval/scoring.py +0 -0
- {hy_memory-2.0.5.dev4 → hy_memory-2.0.7}/hy_memory/pipelines/_retrieval/series_tail_guard.py +0 -0
- {hy_memory-2.0.5.dev4 → hy_memory-2.0.7}/hy_memory/pipelines/_retrieval/session_episode.py +0 -0
- {hy_memory-2.0.5.dev4 → hy_memory-2.0.7}/hy_memory/pipelines/_retrieval/strength.py +0 -0
- {hy_memory-2.0.5.dev4 → hy_memory-2.0.7}/hy_memory/pipelines/_retrieval/supplemental_propositions.py +0 -0
- {hy_memory-2.0.5.dev4 → hy_memory-2.0.7}/hy_memory/pipelines/_retrieval/tag_index.py +0 -0
- {hy_memory-2.0.5.dev4 → hy_memory-2.0.7}/hy_memory/pipelines/_retrieval/temporal.py +0 -0
- {hy_memory-2.0.5.dev4 → hy_memory-2.0.7}/hy_memory/pipelines/_retrieval/topic_candidates.py +0 -0
- {hy_memory-2.0.5.dev4 → hy_memory-2.0.7}/hy_memory/pipelines/_retrieval/trace.py +0 -0
- {hy_memory-2.0.5.dev4 → hy_memory-2.0.7}/hy_memory/pipelines/_retrieval/underflow.py +0 -0
- {hy_memory-2.0.5.dev4 → hy_memory-2.0.7}/hy_memory/pipelines/_retrieval/user_level_l0.py +0 -0
- {hy_memory-2.0.5.dev4 → hy_memory-2.0.7}/hy_memory/pipelines/balanced_catalog.py +0 -0
- {hy_memory-2.0.5.dev4 → hy_memory-2.0.7}/hy_memory/pipelines/cross_domain_sweeper.py +0 -0
- {hy_memory-2.0.5.dev4 → hy_memory-2.0.7}/hy_memory/pipelines/reader.py +0 -0
- {hy_memory-2.0.5.dev4 → hy_memory-2.0.7}/hy_memory/pipelines/reader_hybrid.py +0 -0
- {hy_memory-2.0.5.dev4 → hy_memory-2.0.7}/hy_memory/pipelines/reader_legacy.py +0 -0
- {hy_memory-2.0.5.dev4 → hy_memory-2.0.7}/hy_memory/pipelines/specific_supplement.py +0 -0
- {hy_memory-2.0.5.dev4 → hy_memory-2.0.7}/hy_memory/pipelines/system2_agent.py +0 -0
- {hy_memory-2.0.5.dev4 → hy_memory-2.0.7}/hy_memory/pipelines/system2_tools.py +0 -0
- {hy_memory-2.0.5.dev4 → hy_memory-2.0.7}/hy_memory/pipelines/system2_writer.py +0 -0
- {hy_memory-2.0.5.dev4 → hy_memory-2.0.7}/hy_memory/pipelines/user_profile_scope.py +0 -0
- {hy_memory-2.0.5.dev4 → hy_memory-2.0.7}/hy_memory/runtime.py +0 -0
- {hy_memory-2.0.5.dev4 → hy_memory-2.0.7}/hy_memory/snapshot.py +0 -0
- {hy_memory-2.0.5.dev4 → hy_memory-2.0.7}/hy_memory/structure.py +0 -0
- {hy_memory-2.0.5.dev4 → hy_memory-2.0.7}/hy_memory/utils/async_executor.py +0 -0
- {hy_memory-2.0.5.dev4 → hy_memory-2.0.7}/hy_memory/utils/clone_references.py +0 -0
- {hy_memory-2.0.5.dev4 → hy_memory-2.0.7}/hy_memory/utils/keyword_ties.py +0 -0
- {hy_memory-2.0.5.dev4 → hy_memory-2.0.7}/hy_memory/utils/log_setup.py +0 -0
- {hy_memory-2.0.5.dev4 → hy_memory-2.0.7}/hy_memory/utils/metrics.py +0 -0
- {hy_memory-2.0.5.dev4 → hy_memory-2.0.7}/hy_memory/utils/model_call_context.py +0 -0
- {hy_memory-2.0.5.dev4 → hy_memory-2.0.7}/hy_memory/utils/pipeline_log_writer.py +0 -0
- {hy_memory-2.0.5.dev4 → hy_memory-2.0.7}/hy_memory/utils/pipeline_observability.py +0 -0
- {hy_memory-2.0.5.dev4 → hy_memory-2.0.7}/hy_memory/utils/source_filter.py +0 -0
- {hy_memory-2.0.5.dev4 → hy_memory-2.0.7}/hy_memory/utils/time_window.py +0 -0
- {hy_memory-2.0.5.dev4 → hy_memory-2.0.7}/hy_memory/utils/token_count.py +0 -0
- {hy_memory-2.0.5.dev4 → hy_memory-2.0.7}/hy_memory/utils/trace_file_writer.py +0 -0
- {hy_memory-2.0.5.dev4 → hy_memory-2.0.7}/hy_memory/utils/tracer.py +0 -0
- {hy_memory-2.0.5.dev4 → hy_memory-2.0.7}/hy_memory.egg-info/dependency_links.txt +0 -0
- {hy_memory-2.0.5.dev4 → hy_memory-2.0.7}/hy_memory.egg-info/requires.txt +0 -0
- {hy_memory-2.0.5.dev4 → hy_memory-2.0.7}/hy_memory.egg-info/top_level.txt +0 -0
- {hy_memory-2.0.5.dev4 → hy_memory-2.0.7}/setup.cfg +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: hy-memory
|
|
3
|
-
Version: 2.0.
|
|
3
|
+
Version: 2.0.7
|
|
4
4
|
Summary: HY Memory - Industrial-grade dual-system cognitive memory framework
|
|
5
5
|
Author: alvinfei
|
|
6
6
|
License-Expression: Apache-2.0
|
|
@@ -304,6 +304,7 @@ That version is usually not in the working tree or at HEAD either, so it cannot
|
|
|
304
304
|
- [Graph memory design](docs/pro_graph_design.md) — graph projection, rerank, relation paths, and deployment limits
|
|
305
305
|
- [Environment template](.env.example) — a copy-ready configuration template
|
|
306
306
|
- [MemHub README](memhub/README.md) — local-first desktop & CLI product overview, runtime commands, and privacy boundaries
|
|
307
|
+
- [Hermes native memory provider](plugins/hermes/README.md) — explicit owner/agent scope; separate HTTP service; automatic capture and recall opt-in.
|
|
307
308
|
- [OpenClaw plugin](plugins/openclaw/README.md) — agent integrations live under `plugins/` (overview: [plugins/README.md](plugins/README.md))
|
|
308
309
|
|
|
309
310
|
### License
|
|
@@ -253,6 +253,7 @@ That version is usually not in the working tree or at HEAD either, so it cannot
|
|
|
253
253
|
- [Graph memory design](docs/pro_graph_design.md) — graph projection, rerank, relation paths, and deployment limits
|
|
254
254
|
- [Environment template](.env.example) — a copy-ready configuration template
|
|
255
255
|
- [MemHub README](memhub/README.md) — local-first desktop & CLI product overview, runtime commands, and privacy boundaries
|
|
256
|
+
- [Hermes native memory provider](plugins/hermes/README.md) — explicit owner/agent scope; separate HTTP service; automatic capture and recall opt-in.
|
|
256
257
|
- [OpenClaw plugin](plugins/openclaw/README.md) — agent integrations live under `plugins/` (overview: [plugins/README.md](plugins/README.md))
|
|
257
258
|
|
|
258
259
|
### License
|
|
@@ -65,6 +65,12 @@ from .snapshot import (
|
|
|
65
65
|
|
|
66
66
|
# ====== 配置 ======
|
|
67
67
|
from .config import MemoryConfig
|
|
68
|
+
from .embedding import (
|
|
69
|
+
EmbeddingDimensionMismatchError,
|
|
70
|
+
EmbeddingService,
|
|
71
|
+
EmbeddingServiceProtocol,
|
|
72
|
+
)
|
|
73
|
+
from .retrieval import AmbiguousMemoryIdError, MemoryKind, MemoryVariant
|
|
68
74
|
|
|
69
75
|
# ====== Embedding 端点覆盖(per-call,不改 model/dims,只换接入端点)======
|
|
70
76
|
from .core.embed_service import embed_endpoint_override
|
|
@@ -125,6 +131,13 @@ __all__ = [
|
|
|
125
131
|
"snapshot_local_data_plane",
|
|
126
132
|
# 配置
|
|
127
133
|
"MemoryConfig",
|
|
134
|
+
# 公共扩展协议 / 精确读取类型
|
|
135
|
+
"EmbeddingService",
|
|
136
|
+
"EmbeddingServiceProtocol",
|
|
137
|
+
"EmbeddingDimensionMismatchError",
|
|
138
|
+
"MemoryKind",
|
|
139
|
+
"MemoryVariant",
|
|
140
|
+
"AmbiguousMemoryIdError",
|
|
128
141
|
# Embedding 端点覆盖
|
|
129
142
|
"embed_endpoint_override",
|
|
130
143
|
# 高级 API
|
|
@@ -743,6 +743,7 @@ RECONCILE_PROMPT_ZH = """你是一个记忆整合系统(Memory Reconciler)
|
|
|
743
743
|
|
|
744
744
|
* content
|
|
745
745
|
* owner
|
|
746
|
+
* memory_at(发生时间)
|
|
746
747
|
* tags
|
|
747
748
|
|
|
748
749
|
new memories 没有 ID。
|
|
@@ -791,6 +792,7 @@ new memories 没有 ID。
|
|
|
791
792
|
* 无损合并
|
|
792
793
|
* 保留所有有效信息
|
|
793
794
|
* 不要产生重复 memory
|
|
795
|
+
* 两者在某个值上不一致时,保留 memory_at 更晚的那个值;绝不用更早的 memory 覆盖更新的值
|
|
794
796
|
|
|
795
797
|
### 同一次事件的补充 vs 另一次发生
|
|
796
798
|
|
|
@@ -823,6 +825,7 @@ new memories 没有 ID。
|
|
|
823
825
|
* 新 memory 与旧 memory 在同一维度冲突
|
|
824
826
|
* 两者不能同时为真
|
|
825
827
|
* 旧 memory 已不再代表当前状态
|
|
828
|
+
* 新 memory 的 memory_at 不早于旧 memory 的 memory_at
|
|
826
829
|
|
|
827
830
|
例如:
|
|
828
831
|
|
|
@@ -837,6 +840,7 @@ new memories 没有 ID。
|
|
|
837
840
|
* wording 差异
|
|
838
841
|
* 同义表达
|
|
839
842
|
* 可共存偏好
|
|
843
|
+
* 新 memory 的 memory_at 早于旧 memory:它是更早的状态,绝不能取代更新的状态(见「时间规则」)
|
|
840
844
|
|
|
841
845
|
要求:
|
|
842
846
|
|
|
@@ -859,7 +863,7 @@ new memories 没有 ID。
|
|
|
859
863
|
|
|
860
864
|
### 把多条旧记忆折叠进同一条链
|
|
861
865
|
|
|
862
|
-
|
|
866
|
+
如果**两条或更多**已有记忆描述的是**同一维度**,而新记忆是该维度上的最新变化(它的 memory_at 晚于所有被折叠的记忆),
|
|
863
867
|
你可以把它们折叠进同一条演化链。此时用 `memory_ids`(有序列表,**旧→新**)
|
|
864
868
|
代替单个 `memory_id`:
|
|
865
869
|
|
|
@@ -951,13 +955,16 @@ SUPERSEDE 不需要复制旧内容,因为旧节点仍存在。
|
|
|
951
955
|
|
|
952
956
|
## 时间规则
|
|
953
957
|
|
|
954
|
-
|
|
958
|
+
每条 memory(新的和已有的)都带 memory_at,表示它发生的时间。记忆**不一定按发生顺序写入**:
|
|
959
|
+
历史可能晚导入,导入还没处理完时用户也可能手动添加记忆。所以一条 new memory 可能**比已有记忆更早**。
|
|
955
960
|
|
|
956
|
-
|
|
957
|
-
|
|
958
|
-
|
|
959
|
-
|
|
960
|
-
|
|
961
|
+
* 新旧**只看 memory_at**。"New memories" 只表示"正在写入",不表示"更近"。
|
|
962
|
+
* 更早的 memory 绝不能取代更新的 memory:不能 SUPERSEDE 一条更新的记忆,也不能用 UPDATE 拿更早的值覆盖更新的值。
|
|
963
|
+
* 如果 new memory 比与它冲突的已有记忆更早:保留已有记忆作为当前状态;把 new memory 以"过去状态"ADD
|
|
964
|
+
(用过去时,并带上时间,例如"2023 年用户住在上海"),没有新信息就不输出。
|
|
965
|
+
* `memory_at: null` 表示时间未知。未知**不算更新**:不要用 memory_at 为 null 的 memory 去 SUPERSEDE 一条有时间的记忆。
|
|
966
|
+
* 不要编造时间顺序。
|
|
967
|
+
* 不要仅因为“看起来更新”就 supersede。
|
|
961
968
|
|
|
962
969
|
---
|
|
963
970
|
|
|
@@ -221,6 +221,8 @@ Rules:
|
|
|
221
221
|
* merge losslessly
|
|
222
222
|
* preserve all useful information
|
|
223
223
|
* do NOT create duplicates
|
|
224
|
+
* if the two disagree on a value, keep the value from the memory with the later
|
|
225
|
+
`memory_at`; never let an older memory overwrite a newer value
|
|
224
226
|
|
|
225
227
|
### Same occurrence vs. another occurrence
|
|
226
228
|
|
|
@@ -255,6 +257,7 @@ Use ONLY when:
|
|
|
255
257
|
* the new memory contradicts an existing memory
|
|
256
258
|
* both cannot be true at the same time
|
|
257
259
|
* the old memory would now give the wrong current-state answer
|
|
260
|
+
* the new memory's `memory_at` is the same as or LATER than the existing memory's `memory_at`
|
|
258
261
|
|
|
259
262
|
Examples:
|
|
260
263
|
|
|
@@ -268,6 +271,8 @@ Do NOT use for:
|
|
|
268
271
|
* compatible preferences
|
|
269
272
|
* wording differences
|
|
270
273
|
* semantic equivalence
|
|
274
|
+
* a new memory whose `memory_at` is EARLIER than the existing memory's — it is an
|
|
275
|
+
older state and must never replace a newer one (see "Time order")
|
|
271
276
|
|
|
272
277
|
Rules:
|
|
273
278
|
|
|
@@ -289,7 +294,8 @@ Rules:
|
|
|
289
294
|
### Folding several existing memories into one chain
|
|
290
295
|
|
|
291
296
|
If TWO OR MORE existing memories track the SAME dimension and the new memory is
|
|
292
|
-
the latest change on that dimension
|
|
297
|
+
the latest change on that dimension — its `memory_at` is later than every folded
|
|
298
|
+
memory's `memory_at` — you may fold them into a single evolution
|
|
293
299
|
chain. Use `memory_ids` (an ordered list, OLDEST → NEWEST) instead of a single
|
|
294
300
|
`memory_id`:
|
|
295
301
|
|
|
@@ -318,8 +324,7 @@ older memories' text into it; they remain queryable in the chain history.
|
|
|
318
324
|
* Separate dated occurrences stay separate ADDs; use `same_series` only for the
|
|
319
325
|
same subject and same concrete activity/event type.
|
|
320
326
|
* Keep each memory focused on one coherent topic.
|
|
321
|
-
*
|
|
322
|
-
* `memory_at: null` means unknown time.
|
|
327
|
+
* Follow "Time order" below.
|
|
323
328
|
* **NEVER merge or supersede across different subjects.** The subject is whoever
|
|
324
329
|
the content is about: "The user ..." vs "John ..." vs "Mary ...". Memories about
|
|
325
330
|
different people are independent facts even when the sentence is otherwise
|
|
@@ -332,6 +337,27 @@ older memories' text into it; they remain queryable in the chain history.
|
|
|
332
337
|
|
|
333
338
|
---
|
|
334
339
|
|
|
340
|
+
# Time order
|
|
341
|
+
|
|
342
|
+
Every memory, new or existing, has `memory_at`: when it happened. Memories are
|
|
343
|
+
NOT always written in the order they happened — history can be imported late,
|
|
344
|
+
and a memory can be added while older history is still being processed. A new
|
|
345
|
+
memory can therefore be OLDER than an existing one.
|
|
346
|
+
|
|
347
|
+
* Decide which memory is newer ONLY by `memory_at`. "New memories" means "being
|
|
348
|
+
written now", not "more recent".
|
|
349
|
+
* An older memory must never replace a newer one: no SUPERSEDE of a newer
|
|
350
|
+
memory, and no UPDATE that overwrites a newer value with an older one.
|
|
351
|
+
* If a new memory is older than an existing memory it conflicts with, keep the
|
|
352
|
+
existing memory as the current state. ADD the new one as a past state, worded
|
|
353
|
+
in the past with its time (for example "In 2023 the user lived in Shanghai"),
|
|
354
|
+
or output nothing if it adds no information.
|
|
355
|
+
* `memory_at: null` means unknown time. Unknown is NOT newer: never SUPERSEDE a
|
|
356
|
+
memory that has a known `memory_at` with one whose `memory_at` is null.
|
|
357
|
+
* Do not invent chronology.
|
|
358
|
+
|
|
359
|
+
---
|
|
360
|
+
|
|
335
361
|
# Optional: `related`
|
|
336
362
|
|
|
337
363
|
On any op you MAY add a `related` array recording how the memory being written
|
|
@@ -441,6 +467,81 @@ def append_reconcile_structure_prompt(
|
|
|
441
467
|
return prompt + RECONCILE_STRUCTURE_METADATA_PROMPT_EN
|
|
442
468
|
|
|
443
469
|
|
|
470
|
+
def _as_aware(value: Any) -> Optional[datetime]:
|
|
471
|
+
"""memory_at as a comparable aware datetime; None when unknown or unreadable."""
|
|
472
|
+
if isinstance(value, str) and value:
|
|
473
|
+
try:
|
|
474
|
+
value = datetime.fromisoformat(value)
|
|
475
|
+
except (TypeError, ValueError):
|
|
476
|
+
return None
|
|
477
|
+
if not isinstance(value, datetime):
|
|
478
|
+
return None
|
|
479
|
+
# Stored nodes rebuild memory_at from epoch seconds as naive local time
|
|
480
|
+
# (MemoryNode.from_dict), so a naive value is local, not UTC.
|
|
481
|
+
return value if value.tzinfo is not None else value.astimezone()
|
|
482
|
+
|
|
483
|
+
|
|
484
|
+
def enforce_time_order(
|
|
485
|
+
ops: List["ReconcileOp"],
|
|
486
|
+
new_memory_at: Any,
|
|
487
|
+
existing: Dict[str, Any],
|
|
488
|
+
) -> List["ReconcileOp"]:
|
|
489
|
+
"""An older memory must never replace a newer one, whatever the model says.
|
|
490
|
+
|
|
491
|
+
Memories are not always written in the order they happened: history is
|
|
492
|
+
imported late, and a person can add a memory while older history is still
|
|
493
|
+
being processed. The prompt tells the model to compare `memory_at`; this
|
|
494
|
+
makes it hold. A SUPERSEDE or UPDATE aimed at an existing memory whose
|
|
495
|
+
`memory_at` is later than the memory being written is turned into an ADD,
|
|
496
|
+
so the newer memory stays the current state. Unknown times are not
|
|
497
|
+
compared. A content-less UPDATE (the legacy DELETE mapping) is dropped.
|
|
498
|
+
"""
|
|
499
|
+
written_at = _as_aware(new_memory_at)
|
|
500
|
+
if written_at is None:
|
|
501
|
+
return ops
|
|
502
|
+
kept: List[ReconcileOp] = []
|
|
503
|
+
for op in ops:
|
|
504
|
+
if op.op not in ("SUPERSEDE", "UPDATE"):
|
|
505
|
+
kept.append(op)
|
|
506
|
+
continue
|
|
507
|
+
targets = list(op.memory_ids) if op.memory_ids else [op.memory_id]
|
|
508
|
+
newer = [
|
|
509
|
+
target for target in targets
|
|
510
|
+
if target and (node := existing.get(target)) is not None
|
|
511
|
+
and (target_at := _as_aware(getattr(node, "memory_at", None))) is not None
|
|
512
|
+
and target_at > written_at
|
|
513
|
+
]
|
|
514
|
+
if not newer:
|
|
515
|
+
kept.append(op)
|
|
516
|
+
continue
|
|
517
|
+
logger.warning(
|
|
518
|
+
"[reconciler] %s blocked: memory_at %s is older than existing %s; "
|
|
519
|
+
"kept the newer memory",
|
|
520
|
+
op.op, written_at.isoformat(), ",".join(newer),
|
|
521
|
+
)
|
|
522
|
+
if not op.content:
|
|
523
|
+
continue
|
|
524
|
+
kept.append(ReconcileOp(
|
|
525
|
+
op="ADD",
|
|
526
|
+
content=op.content,
|
|
527
|
+
layer=op.layer,
|
|
528
|
+
owner=op.owner,
|
|
529
|
+
tags=list(op.tags),
|
|
530
|
+
tag_ners=list(op.tag_ners),
|
|
531
|
+
topic_paths=list(op.topic_paths),
|
|
532
|
+
event_facet=dict(op.event_facet),
|
|
533
|
+
topic_assignments=list(op.topic_assignments),
|
|
534
|
+
structure_references=list(op.structure_references),
|
|
535
|
+
topic_paths_provided=op.topic_paths_provided,
|
|
536
|
+
event_facet_provided=op.event_facet_provided,
|
|
537
|
+
topic_assignments_provided=op.topic_assignments_provided,
|
|
538
|
+
speculate=op.speculate,
|
|
539
|
+
related=list(op.related),
|
|
540
|
+
reason=f"time_order: older than {','.join(newer)}; {op.reason}"[:500],
|
|
541
|
+
))
|
|
542
|
+
return kept
|
|
543
|
+
|
|
544
|
+
|
|
444
545
|
def build_reconcile_prompt(
|
|
445
546
|
*,
|
|
446
547
|
new_memories: List[str],
|
|
@@ -1399,6 +1500,7 @@ class MemoryReconciler:
|
|
|
1399
1500
|
_tok_total += response.tokens_used
|
|
1400
1501
|
raw_response = response.content
|
|
1401
1502
|
ops = self._parse_ops(raw_response)
|
|
1503
|
+
ops = enforce_time_order(ops, current_time, candidate_map)
|
|
1402
1504
|
ops = self._inherit_exact_input_structure(
|
|
1403
1505
|
ops, new_memories_with_meta,
|
|
1404
1506
|
)
|