s09: select_relevant_memories 的 "recent" 拼接顺序与切片不合理,不是真正的最近 2k 上下文
I maintainer di solito rispondono entro 15 giorni
Valutazione
- Difficoltà
- 2/5
- Tempo stimato
- 1-3 ore
- Idoneità per principianti
- 78/100
Direzione di ricerca
Inizia in s09_memory/code.py, all’altezza di recent_user_text, in particolare alle righe 251-261, e verifica come vengono raccolti, concatenati e tagliati i messaggi dell’utente. Verifica il comportamento scelto con turni recenti brevi e lunghi; è completo quando il contesto restituito mantiene l’ordine cronologico e include la parte finale degli ultimi 4000 caratteri.
Scritto dal modello di indicizzazione a partire dal testo della issue.
Descrizione
问题
s09_memory/code.py:251-261 recent_user_text returns a string claiming to be the most recent user context, but the join + slice order produces an unintuitive result.
def recent_user_text(messages: list, max_turns: int = 3) -> str:
turns = []
for message in reversed(messages):
if message.get("role") != "user":
continue
text = message_text(message).strip()
if text:
turns.append(text)
if len(turns) == max_turns:
break
return "\n".join(reversed(turns))[:4000]
Actual behavior
reversed(messages)walks backwards;turnsaccumulates up tomax_turns=3user texts inturns = [latest, prev, prev2]order.reversed(turns)then flips it back to[prev2, prev, latest].- Joined with
\n, sliced to head 4000 chars.
Consequences:
- If the latest user turn is short (e.g. "ok"), the head-4000 fills with older turns and the latest one is pushed past the slice window — the most relevant signal is dropped.
- If the latest turn is long, older turns are pushed out entirely and the function degrades to "use only the latest turn" — but that intent is not expressed in the code.
- The function is named
recent_user_textbut the implementation is "oldest of the recent few, then head-slice". Order is non-obvious.
Expected behavior
recent_user_text should mean "the last N characters of the most recent user context, in chronological order". A minimal fix:
def recent_user_text(messages: list, max_chars: int = 4000) -> str:
chunks = []
for message in messages:
if message.get("role") != "user":
continue
text = message_text(message).strip()
if text:
chunks.append(text)
joined = "\n".join(chunks)
return joined[-max_chars:] if len(joined) > max_chars else joined
Or, if preserving the per-turn walk is desired, take only the tail of the result rather than the head:
result = "\n".join(reversed(turns))
return result[-4000:] if len(result) > 4000 else result
Either is fine — the important thing is that the slice direction matches the name: "recent" means tail, not head.
中文版本
问题
s09_memory/code.py:251-261 recent_user_text 的字面意思虽然是"最近的用户文本",但 join + 切片的顺序让它产出一个反直觉的结果。
```python
def recent_user_text(messages: list, max_turns: int = 3) -> str:
turns = []
for message in reversed(messages):
if message.get("role") != "user":
continue
text = message_text(message).strip()
if text:
turns.append(text)
if len(turns) == max_turns:
break
return "\n".join(reversed(turns))[:4000]
```
实际行为
- `reversed(messages)` 从末尾向前扫描,收集最多 3 条 user 文本,此时 `turns` 顺序为 `[最新, 次新, 更旧]`。
- `reversed(turns)` 又翻回 `[更旧, 次新, 最新]`。
- 用 `\n` 拼接后取头 4000 字符。
带来的问题:
- 如果最新那条很短(比如 "ok"),头 4000 字符会被更旧的消息灌满,最新那条反而被切掉——最该被命中的信号反而丢
- 如果最新那条够长,前面的消息直接被挤出窗口,函数退化成"只用最新一条"——这个意图代码里没体现
- 函数名叫 `recent_user_text`,实现却是"最近几条里最旧的先出现 + 头切",顺序含义不明
期望行为
`recent_user_text` 应该是"按时间正序排列后,取末尾 N 个字符"。最小修复:
```python
def recent_user_text(messages: list, max_chars: int = 4000) -> str:
chunks = []
for message in messages:
if message.get("role") != "user":
continue
text = message_text(message).strip()
if text:
chunks.append(text)
joined = "\n".join(chunks)
return joined[-max_chars:] if len(joined) > max_chars else joined
```
或者保留逐条遍历的写法,但把切片方向反过来:
```python
result = "\n".join(reversed(turns))
return result[-4000:] if len(result) > 4000 else result
```
任选其一即可,关键是切片方向跟函数名一致——"recent" 是尾部,不是头部。
- Lingua principale
- Python
- Stelle
- 79.5k
- Fork
- 12.7k
- Merge medio
- 11g 19h
- PR unite (30g)
- 5
Preparare l'ambiente
- Nessun Dockerfile né file Docker Compose
- Nessun modello di pull request
- Leggi la guida per i contributori
Come iniziare
- Leggi tutta la issue e poi la guida ai contributi del progetto.
- Commenta sulla issue per dire che te ne occupi tu — evita che due persone facciano lo stesso lavoro.
- Fai un fork del repository e lavora su un branch.
- Apri una pull request che faccia riferimento al numero della issue.
Altre issue di shareAI-lab/learn-claude-code
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 75/100
shareAI-lab/learn-claude-code#583 ·
I maintainer di solito rispondono entro 15 giorni
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 72/100
shareAI-lab/learn-claude-code#528 ·
I maintainer di solito rispondono entro 15 giorni
-
s17: IDLE teammates cannot resume their own in-progress tasksForse già presa @hichipli l’ha presa 60 giorni fa. Aperta
Difficoltà 2/5 1-3 ore Idoneità per principianti 84/100
shareAI-lab/learn-claude-code#519 ·
I maintainer di solito rispondono entro 15 giorni
-
plan_approval_response 不会唤醒 idle teammateForse di nuovo libera Una pull request per questa issue è stata chiusa senza essere unita. Aperta
Difficoltà 2/5 1-3 ore Idoneità per principianti 72/100
shareAI-lab/learn-claude-code#455 ·
I maintainer di solito rispondono entro 15 giorni
-
Difficoltà 1/5 Meno di un'ora Idoneità per principianti 52/100
shareAI-lab/learn-claude-code#605 ·
I maintainer di solito rispondono entro 15 giorni
Tutte le issue di shareAI-lab/learn-claude-code
Issue simili
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 82/100
I maintainer di solito rispondono entro 2 giorni
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 86/100
-
Validate finite output clamping limits in StepPredictor.prepare_clamping_params to prevent silent NaN/Inf propagationForse già presa @muskan-creates352 l’ha presa oggi. Aperta
Difficoltà 2/5 1-3 ore Idoneità per principianti 84/100
mllam/neural-lam#848 ·
I maintainer di solito rispondono entro 2 giorni
-
infra
Difficoltà 1/5 Meno di un'ora Idoneità per principianti 88/100
fab-geocommuns/RNB-coeur#1166 ·
I maintainer di solito rispondono entro 1 giorno
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 78/100
deepspeedai/DeepSpeed#8951 ·
I maintainer di solito rispondono entro 2 giorni