-
Notifications
You must be signed in to change notification settings - Fork 163
11_04_Memory_System
记忆系统在 cli/memory.py,只服务 CLI(命令行)/ TUI(终端图形界面)。
它不是聊天记录归档,也不是持仓数据库。它的目的只有一个:让后续交易判断持续遵守用户已经确认过的交易纪律,例如不追涨、偏好尾盘二次确认、跌破确认支撑不买、极端放量冲高回落不买。
因此,记忆系统只沉淀稳定、可复用的信息;每天行情、当前持仓、某只股票今天能不能买、工具调用细节,都不应该进入长期记忆。这些内容应该来自实时工具、推荐表、持仓表、信号表或 chat log。
L1、L2、L3 表示信息的抽象方式,不表示谁比谁“更高级”、也不表示 L3 一定覆盖 L2。
flowchart TD
L1["L1 原子记忆<br/>偏好 / 决策"] --> L2["L2 交易剧本<br/>什么场景下怎么做"]
L1 --> L3["L3 用户画像<br/>这个用户长期是什么交易风格"]
| 层级 | 存储类型 | 解决的问题 | 典型内容 | 不该放什么 |
|---|---|---|---|---|
| L1 |
preference / decision
|
记录原始证据 | “用户偏好尾盘买入”;“跌破确认支撑不买” | 今日行情、一次性买卖、工具执行过程 |
| L2 | playbook |
把多个 L1 归纳成可执行流程 | “尾盘二次确认买入剧本:14:45 后检查支撑、VWAP、量能;破支撑不买” | 泛泛的投资理念、没有触发条件的口号 |
| L3 | persona |
把多个 L1 归纳成用户画像 | “用户重视本金安全,偏好二次确认,不喜欢开盘交易影响情绪” | 临时市场观点、某只股票当前结论 |
三者的使用方式不同:
- L1 是证据:回答“这条规则从哪里来”。
- L2 是动作:回答“遇到这个交易场景应该怎么执行”。
- L3 是约束:回答“这个用户整体是什么风险偏好和交易性格”。
举例:
L1:
- [preference] 用户不想每天开盘买,容易影响心情
- [preference] 用户倾向尾盘买入
- [decision] 当天跌破确认支撑不买
- [decision] 极端放量但冲高回落不买
L2:
- [playbook] 尾盘二次确认买入:适用于已进入候选池且需要二次确认的股票;14:45 后检查支撑、VWAP、收盘位置和量能;跌破确认支撑或极端放量冲高回落时禁止买入。
L3:
- [persona] 用户重视本金安全和交易情绪稳定,偏好二次确认,不喜欢开盘冲动交易。
所以,L2 和 L3 是从同一批 L1 派生出的两个维度:L2 面向交易动作,L3 面向用户画像。
对话结束或新开会话时,save_session_summary() 在后台线程异步执行。触发前先做轻量门控,任一不满足则跳过:
- 消息总数 ≥ 4 条
- 本轮对话有工具调用(纯聊天不值得提取)
- provider(模型适配层)已配置
- 当前 session(会话)的摘要 hash(哈希)没有处理过;如果
/new、resume(恢复会话)、fork(分叉会话)或退出重复触发同一批消息,直接跳过,不再请求 LLM
满足条件后,系统会把对话消息转换成摘要输入文本,再发给 LLM 用 _SESSION_SUMMARY_PROMPT 提取。摘要输入不是直接取原始 messages[-40:],而是先遍历全部消息,将非空 content 格式化成 [role] content 文本行;其中 role=tool 的工具结果如果超过 200 字,会先截断到 200 字。最后取这些文本行的最后 40 行。只有 tool_calls、没有 content 的 assistant 消息不会进入摘要输入。
Prompt 只允许输出两种格式:
[偏好] 用户偏好尾盘二次确认,不想开盘买入影响情绪
[决策] 当天跌破确认支撑不买
解析后按标签写入 SQLite:[偏好] → preference(L1),[决策] → decision(L1)。无论提取结果是否写入新 L1,系统都会写入一个 session marker(处理标记),记录 summary_hash,用于避免同一批消息重复摘要;这个 marker 不参与召回注入。
如果一条 L1 内容自身包含 6 位代码或明确股票名称,写入前会用本地股票名称缓存解析成 codes,用于后续确定性召回;没有明确股票的全局交易纪律保持 codes=''。这样可以避免“本轮聊过宁德时代,所以不追涨这条全局偏好也被误绑到宁德时代”。
写入前经过两级去重。第一层是 确定性去重:对同类型已有记忆做规范化文本比较和字符 bigram(双字片段)相似度判断,完全重复或高度相似时直接跳过,不调用 LLM。
第二层是 LLM 语义去重:当同类型已有记忆存在,且确定性规则未判定重复时,系统会使用 fallback provider(不可用时复用当前 provider)把新内容和最近 10 条同类型记忆一起发给 _DEDUP_PROMPT 判断。只有明确判定为 NEW 的内容才写入 L1;如果语义去重调用失败、返回格式无效,或返回了不存在的重复记忆 id,系统会跳过本条写入,避免未经确认的重复记忆进入长期记忆。
每次成功写入至少一条新 L1,且 skip_layers=False 时,会尝试触发 refresh_memory_layers()。触发不等于一定调用 LLM,系统先做增量门控:
atoms = get_recent_L1_preference_and_decision(limit=30)
if len(atoms) < 3:
return 0
source_hash = hash(atoms)
if source_hash 已经被 L2/L3 记录过:
return 0
if 不是首次蒸馏 and 新增 L1 数量 < 3:
return 0_LAYER_REFRESH_PROMPT 要求 LLM 基于最近 L1 归纳两类高层记忆,每类最多 3 条:
[画像] 用户重视本金安全和情绪稳定,偏好尾盘二次确认
[剧本] 尾盘二次确认买入:适用于已进入候选池的股票;14:45 后检查支撑、VWAP、收盘位置和量能;跌破确认支撑或极端放量冲高回落时禁止买入
解析标签后写入:[画像] → persona(L3),[剧本] / [交易剧本] → playbook(L2)。历史 scenario 记录仅做兼容召回;新生成的 L2 统一写入 playbook。
每条由层级蒸馏生成的 L2/L3 都会在 metadata 中记录:
extractor=layer_refreshlayer_versionsource_l1_idssource_hash
关键设计:L2/L3 不是“某条 L1 被升级”,而是“最近一批 L1 被重新归纳”。原始 L1 仍然保留,L2/L3 只是在它们之上生成可复用摘要。系统每次蒸馏仍读取最近 30 条 L1 以保留全局语境,但只有当 source hash 未处理过,且距离上次蒸馏至少新增 3 条 L1 时才真正调用 LLM。这样避免同一批 L1 被反复重算,也降低 L2/L3 被同义改写污染的概率。
flowchart TD
A["对话结束 / 新会话"] --> B{"消息 ≥ 4 条\n且有工具调用"}
B -->|否| Z["跳过"]
B -->|是| H0{"session summary_hash\n是否已处理"}
H0 -->|是| Z
H0 -->|否| C["取最近 40 条消息\n工具结果截断至 200 字"]
C --> D["LLM 提取\n最多 3 条 [偏好] / [决策]"]
D --> E{"确定性去重\n规范化文本 / bigram 相似度"}
E -->|重复| M["写 session marker"]
E -->|新内容| E2{"同类型已有记忆"}
E2 -->|否| F["写入 SQLite\nL1 preference / decision"]
E2 -->|是| E3{"LLM 语义去重\n与已有 10 条对比"}
E3 -->|重复或失败| M
E3 -->|NEW| F
F --> M
M --> G{"是否退出场景\nskip_layers"}
G -->|是| Z
G -->|否| H{"L1 总数 ≥ 3 条"}
H -->|否| Z
H -->|是| I{"source_hash 是否处理过\n或新增 L1 不足 3 条"}
I -->|是| Z
I -->|否| J["取最近 30 条 L1\n发给 LLM 蒸馏"]
J --> K["LLM 输出 [画像] / [剧本]"]
K --> L2["L2 playbook\n条件化交易剧本"]
K --> L3["L3 persona\n用户稳定画像"]
L2 --> W["写入 SQLite\nmetadata 记录 source_l1_ids / source_hash"]
L3 --> W
| 类型 | 上限 | 清理策略 |
|---|---|---|
preference |
50 条 | 超出后删最旧;永不因时间衰减降权;长期保留 |
decision |
30 条 | 超出后删最旧;45 天后被 prune_memories 清理 |
playbook |
20 条 | 超出后删最旧;60 天后清理 |
persona |
5 条 | 超出后删最旧;永久保留,不受时间清理影响 |
scenario |
兼容类型 | 旧版本 L2 记录,按 playbook 规则召回和清理 |
召回入口流程总览:
flowchart TD
U["当前用户消息"] --> C["解析股票代码 / 股票名称"]
U --> K["抽取中文关键词"]
U --> F["FTS5 全文检索"]
U --> A["历史归档检索 (search_context_archives)"]
C --> S["代码精确匹配"]
K --> L["关键词 LIKE 匹配"]
F --> R["混合排序 + 类型半衰期"]
S --> R
L --> R
R --> P["Persona / Preference 置顶"]
P --> D["按 id 去重"]
D --> I["注入 relevant-memories"]
A --> AR["提取匹配归档引用 (archive_recall_lines)"]
AR --> ARC["追加 # 压缩归档"]
I --> OUT["合并后的记忆上下文"]
ARC --> OUT
召回由 build_memory_context()(cli/memory.py)驱动,底层实现在 search_memory_hybrid()(integrations/local_db.py)以及 cli/context_archive.py。每次用户发送消息,系统先把 6 位代码和本地股票名称解析成确定性 codes,再并行启动四路独立检索管道,结果进行合并、去重、过滤和追加排序。
股票作用域过滤是防止错召的关键:
- 当前问题能解析出明确股票时,只保留全局记忆和同代码记忆。例如“我想建仓比亚迪”会解析到
002594,不会召回300750宁德时代的单股建仓记忆。 - 当前问题没有明确股票时,带
codes的单股记忆不参与召回。例如“我想建仓科技”不会因为“科技”两个字召回“长信科技”的单股记忆。 -
科技、白酒这类词属于板块/主题,不等同于股票名;它们可以作为未来主题记忆的实体,但不能靠股票代码确定性召回。
管道一:FTS5 全文检索(权重 0.8)
将用户原始消息直接提交给 SQLite FTS5 虚拟表:
SELECT m.*, bm25(agent_memory_fts) AS rank
FROM agent_memory_fts fts
JOIN agent_memory m ON m.id = fts.rowid
WHERE agent_memory_fts MATCH '用户输入'
ORDER BY rankFTS5 使用 SQLite 默认 unicode61 tokenizer 建立倒排索引后用 BM25 排序。BM25 同时考虑词频(TF)和逆文档频率(IDF),比单纯 LIKE 匹配更精准,也能容忍部分字段不完整匹配;中文短词覆盖主要由后面的关键词 2-gram 管道兜底。
管道二:股票实体精确匹配(权重 1.2)
正则 (?<!\d)(\d{6})(?!\d) 从用户输入中抽取 6 位股票代码,同时使用本地 stock_list_cache.json 做股票名到代码的最长匹配。例如“宁德时代”映射为 300750,“比亚迪”映射为 002594,然后对 codes 字段做 LIKE 匹配:
WHERE codes LIKE '%300750%'代码命中说明这条记忆明确与当前股票相关。FTS5 和关键词召回得到的候选也会经过同样的代码作用域过滤,避免同一个“建仓”泛词把其它股票的历史记忆带进来。
管道三:中文关键词 LIKE 匹配(权重 0.25)
_extract_keywords() 对用户输入做轻量分词:
- 正则
[一-鿿]{2,4}抓出所有 2~4 字中文片段。 - 超过 2 字的片段按 2-gram 滑窗拆分("建仓位置"→"建仓"+"仓位"+"位置"),提高短词召回率。
- 过滤停用词和泛交易词("可以"、"现在"、"建仓"、"买入"、"止损" 等)。
- 去重,取前 5 个关键词。
对每个关键词做 content LIKE %keyword%,多词 OR 合并查询,命中任意一词即得分。权重最低,用于兜底覆盖 FTS5 未建索引的边角情况。
管道四:历史归档元数据检索(Context Archive Recall)
在上下文压缩发生后,历史高保真消息已移出活跃上下文,被持久化为本地 context_archive/{session_id}/{compaction_id}.jsonl。为防止信息永久丢失,系统利用元数据进行召回:
- 提取关键词:系统将用户当前消息提取股票代码及 2-gram 中文词,构建为查询项集合。
-
元数据匹配:扫描当前 session 下(或全局)所有
.json元数据索引文件,通过_meta_score算法计算查询项在元数据的compaction_id、summary、codes、files和keywords字段中的匹配交集数量。 -
加权排序:匹配交集得分大于 0 的元数据记录,按照匹配得分及
created_at时间戳降序排序,筛选出排名前 2 的归档元数据记录(通过archive_recall_lines)。 -
注入上下文:归档不参与传统 memory 混排,而是在内存拼接时单独作为一个
# 压缩归档部分注入:# 压缩归档 - archive://default/ctx_20260621120000_abcd12345678 [002594]:关于比亚迪突破120日均线的建仓位置讨论与策略规划。
-
主动恢复(Recovery):
如果 Agent 发现用户提到了归档中涉及的旧内容(例如“我们上次谈到比亚迪突破120日线,那个具体策略是什么”),由于上下文中有
# 压缩归档下的具体 URIarchive://...,Agent 可以主动使用query_history(source="archive", archive_ref="archive://default/ctx_...")工具读取该归档下的完整消息流以了解详细历史,实现无缝的历史接力。
针对数据库召回的 L1/L2 记忆(FTS5、代码精确、中文关键词):
candidates: dict[int, dict] = {} # key = 记忆 id
def _merge(items, source_weight):
for m in items:
if m["id"] not in candidates:
m["_score"] = source_weight
candidates[m["id"]] = m
else:
candidates[m["id"]]["_score"] = max(已有分, source_weight)同一条记忆被多个管道命中,得分取三者中的最大值,不叠加。这样避免"被多个低质量管道重复命中的普通记忆"压过"只被 FTS5 精准命中的高质量记忆"。
所有候选记忆都乘以时间衰减系数,默认半衰期 14 天;L2 交易剧本稍长,L3 画像和长期偏好不衰减:
| 类型 | 半衰期 | 自动清理 |
|---|---|---|
decision |
14 天 | 45 天 |
playbook / scenario
|
21 天 | 60 天 |
stock_opinion / market_view / fact
|
14 天 | 30-45 天 |
preference / persona
|
不衰减 | 长期保留 |
这样做的目的,是让阶段性单股判断和交易剧本更快让位于新反馈;用户的长期偏好和风险边界仍然稳定保留。
记忆系统的判断标准不是“这句话重要不重要”,而是“它以后是否能稳定改善交易决策”。
| 信息 | 是否进记忆 | 推荐落点 |
|---|---|---|
| “我不想开盘买,影响心情” | 是 | L1 preference,后续可蒸馏进 L3 persona
|
| “跌破确认支撑不买” | 是 | L1 decision,后续可蒸馏进 L2 playbook
|
| “尾盘二次确认后再买” | 是 | L1 preference / L2 playbook
|
| “今天泛微网络可以买吗” | 否 | 当前工具分析 / chat log |
| “我现在持有 4 只股票” | 否 | portfolio / Supabase 持仓表 |
| “今天市场资金撤退明显” | 否 | 市场数据表 / 当日报告 |
| “某次工具调用失败” | 否 | agent log / scratchpad |
投资场景里有一类信息变化很快:今天认为黄金有避险价值,明天觉得黄金逻辑失效、科技主线更强,后天又认为白酒长期下跌后有修复机会。这类内容不能简单当成长期画像覆盖,也不能只保留最后一句,否则会丢失用户决策风格中的“切换条件”。
当前实现采用 追加式记忆 + 当前轮召回 ,而不是覆盖式记忆:
-
临时交易指令默认不沉淀:
_SESSION_SUMMARY_PROMPT明确要求不要提取具体买卖事实、临时操作和当天市场状态。 -
阶段性判断优先落在 L1
decision:如果用户表达的是“因为某个逻辑失效,所以从黄金切到科技”,这更像决策逻辑,而不是永久偏好。 -
稳定风格才进入
preference/persona:例如“不追涨”、“重视止损”、“单票仓位不超过 15%”,才适合长期置顶。 -
旧判断不自动删除:系统保留
created_at和source_ref,让模型看到用户观点变化的时间顺序,也能用wyckoff memory trace <id>回看来源。 -
召回只作为参考:记忆被包在
`<relevant-memories>`中,并声明"不代表当前任务进程,仅作为参考",当前问题和工具实时数据仍然优先。
因此,黄金、科技、白酒这类主线切换更适合作为阶段性 decision 或 L2 playbook 的触发条件被召回,而不是永久 persona。当前系统能保留变化过程和来源证据,但还没有显式的 superseded(被新观点取代)状态;如果后续要更严格处理冲突,可以在 agent_memory.metadata 中增加 topic_key、valid_until、superseded_by 等字段,用于把同一主题下的旧观点标记为已被覆盖。
persona(L3)和 preference(L1)还额外走一条旁路,不参与 hybrid search 的分数竞争,直接按时间取最新的(persona 取 1 条,preference 取 5 条),在最终组装时强制排在最前。
注意这里不是 L3 全量召回:当前只无条件置顶最新 1 条 persona。playbook(L2)走 hybrid search,只有和当前 query 相关时才进入“# 交易剧本”。
置顶后的 persona / preference 会按 memory id 从 hybrid 结果里去重,避免同一条偏好既出现在"# 用户画像",又出现在"# 历史记忆":
# 用户画像(persona + preference,置顶)
# 交易剧本(playbook / legacy scenario,hybrid search 命中,最多 3 条)
# 历史记忆(decision 等,hybrid search 命中)
全部内容组装后经 _budget_recall_lines() 做 token 预算截断:每条记忆不超过 200 字符,所有召回内容合计不超过 1200 字符。超出时从末尾截断,保证注入体积不会对上下文窗口造成压力。
注入格式通过 prepend_memory_context() 把召回记忆包在 `<relevant-memories>`(相关记忆)中,再把当前用户消息包在 `<current-user-message>`(当前用户消息)中。这样模型可以参考长期偏好,但不会把记忆误当成当前任务进度。
记忆召回的注入采用 瞬态注入(Transient Injection) 模式:注入→发送→还原,只活在当前轮,不污染历史消息。
第一步:构建并暂存(_send_message,tui.py)
用户发出消息后,先调用 build_memory_context(text) 做 hybrid search 召回记忆,结果暂存在私有字段 _memory_context 里,此时 messages[-1]["content"] 仍是原始用户输入:
user_message = {"role": "user", "content": text}
if mem_ctx:
user_message["_memory_context"] = mem_ctx # 暂存,不直接污染 content
self._messages.append(user_message)第二步:发送前注入(_prepare_turn_memory_context,tui.py)
_run_agent() 启动时立即调用,把记忆从 _memory_context 弹出并 prepend 到 content 前,原始文本备份到 _raw_content:
self._messages[turn_index]["_raw_content"] = user_text # 备份原文
self._messages[turn_index]["content"] = prepend_memory_context(user_text, memory_context)实际发给模型的 content 格式如下:
<relevant-memories>
以下是当前对话召回的相关记忆,不代表当前任务进程,仅作为参考:
# 用户画像
- [persona] 用户重视本金安全和情绪稳定,偏好尾盘二次确认
- [preference] 用户不想开盘买入,避免影响一天心情
# 交易剧本
- [playbook] 尾盘二次确认买入:14:45 后检查支撑、VWAP、收盘位置和量能;破支撑不买
# 历史记忆
- [decision] 极端放量但冲高回落不买
</relevant-memories>
<current-user-message>
宁德时代现在可以建仓吗
</current-user-message>第三步:回复后还原(_restore_turn_user_message,tui.py)
模型回复结束后,把 content 从注入版本恢复为原始用户输入:
msg["content"] = msg.pop("_raw_content") # 擦除注入,还原原文| 方案 | 问题 |
|---|---|
| 改 System Prompt | 记忆持续占用所有后续轮次 token;每轮重建 system prompt 会破坏静态基底缓存 |
| Prepend 到当前轮 user message(当前实现) ✅ | 只影响当前轮;用后擦除;记忆与当前问题绑定,模型关联度更高 |
Section 2 描述的 滑动提示词缓存 依赖前缀稳定性:只有发给 API 的 messages 前缀与上一次请求完全一致,才能命中缓存。
还原后,每轮发出的历史消息结构如下:
第 N+1 轮发出的 messages(还原后):
system | u1 | a1 | u2 | a2 | ... | u(N-1) | a(N-1) | uN(还原后) | aN | uN+1+记忆
←────────── 全部命中第 N 轮的缓存 ──────────────────→ ↑miss(因为缓存里是 uN+记忆)
每轮固定只 miss 上一轮的最后一条 user message(因为那条发出时带了注入的记忆,还原后变成干净原文,与缓存不一致)。其余所有更早的历史消息前缀完全稳定,全部命中缓存。
| 对话轮次 N | 历史消息总数 | 每轮 miss 条数 | miss 比例 |
|---|---|---|---|
| 2 | 2 | 1 | 50%(短对话损失大) |
| 5 | 8 | 1 | 12.5% |
| 10 | 18 | 1 | 5.6% |
| 20 | 38 | 1 | 2.6%(趋近于零) |
缓存 miss 的代价是固定 O(1) 的,不随对话增长而扩大。
与不还原相比(记忆永久残留在历史里):不还原时历史消息同样稳定,缓存命中率反而略好,但代价是每轮记忆文本(~500 token)持续堆积在 context 里,20 轮后额外占用 10,000+ token。
**结论 :「用后擦除」的核心价值是 ** 防止上下文无限膨胀 ,同时把缓存 miss 的代价锁定在固定 1 条,不让脏历史随轮次扩散。缓存方面不是零损耗,但随对话增长趋近无影响。
每条记忆保留 `source_ref=chat_log:<session_id>`(来源引用)。CLI(命令行)可用 `wyckoff memory trace <id>` 回看来源,避免长期摘要变成不可验证黑盒。
注意:agent_memory 和 context_archive 是两套不同机制。agent_memory 只保存可跨会话复用的长期偏好、交易纪律和决策剧本;context_archive 保存被上下文压缩移出主窗口的原始消息,用于同一类问题的证据恢复。前者用于“以后怎么做得更符合用户”,后者用于“刚才/之前具体发生了什么还能找回来”。
记忆系统只负责“用户长期怎么交易”,不负责“今天发生了什么”。交易系统里的事实数据应继续留在结构化表和工具返回中:
| 内容 | 正确来源 |
|---|---|
| 当前持仓、成本、盈亏 | portfolio / Supabase 持仓表 |
| 今日推荐、AI 是否推荐、二次确认原因 | recommendation / signal 表 |
| 今日市场状态、资金趋势、板块水温 | 每日漏斗报告 / 市场数据工具 |
| 某只股票今日 K 线和分钟线 | TickFlow / Tushare / 行情工具 |
| Agent 当时怎么想、调用了什么工具 | scratchpad / chat log / agent log |
| 被上下文压缩移出的原始消息 | context archive / archive://...
|
| 用户稳定偏好、交易禁忌、可复用执行剧本 | agent_memory |
这个边界很重要:如果把短期行情塞进长期记忆,后续模型会把过期事实误当成当前事实;如果把交易纪律只放在一次对话里,后续又会忘记用户的风控习惯。
每次用户消息进入会话,系统在后台并发执行以下四种召回方式:
-
FTS5 全文检索 (SQLite):
利用 SQLite 倒排索引进行 BM25 评分(基于词频 TF 和逆文档频率 IDF 算法)。权重系数设为
0.8。适用于匹配用户表达的复杂自然语言场景(如“上一次谈到仓位管理时是怎么说的”)。 -
股票实体精确匹配:
通过正则从用户输入中提取 6 位股票代码(如
603373),或匹配stock_list_cache.json缓存在输入中出现的最长股票名称,将其映射为 codes。然后在记忆库中执行codes LIKE '%ticker%'。权重系数设为1.2。 -
2-gram 中文滑窗分词:
去除停用词(如“买入”、“现在”等通用交易词)后,将中文片段按 2 字滑窗切分。执行
content LIKE %keyword%检索。权重系数设为0.25,用于补充全文检索可能遗漏的边角关联词。 -
历史归档元数据匹配:
扫描
context_archive目录下的.json元数据索引文件,利用_meta_score计算查询项在摘要、标的代码、修改文件以及提取关键字中的命中频次。该路匹配获取的归档不参与传统记忆混排,直接作为# 压缩归档部分追加到提示词尾部。
同一条 L1/L2 记忆如果被多个管道同时命中,系统采用取最大值而不累加的策略:
这有效防止了一条记忆仅因为包含了大量普通泛词(被 keyword LIKE 命中多次)而压过了高相关度精确匹配的记忆。
为确保阶段性观点与决策的及时更新,防止过期剧本干扰最新策略,系统对记忆进行时间加权衰减:
-
decision(阶段决策):半衰期 14 天,45 天后物理清理。 -
playbook(交易剧本):半衰期 21 天,60 天后物理清理。 -
preference/persona(画像与稳定偏好):不参与衰减,永久保留。
返回 系列索引
- Home
- 01_Product_Overview
- 02_Finance_Wyckoff_Method
- 03_Finance_Quantitative_Metrics
- 04_Finance_Sector_Rotation_Regime
- 05_Finance_Risk_Management
- 06_Backtest_Methodology
- 07_Backtest_Simple_vs_Compound
- 08_Research_Strategy_Decay
- 09_Tech_Architecture
- 10_Tech_LLM_RAG_Integration
- 12_Tech_Actions_Operations
- 13_Tech_Python_Engineering