Skip to content

Fix #2121: [Bug] memos-local-plugin: embedding source text exceeds embedding-3's 3072-token#2123

Open
Memtensor-AI wants to merge 19 commits into
MemTensor:dev-v2.0.25from
Memtensor-AI:bugfix/autodev-2121-20260719143800575
Open

Fix #2121: [Bug] memos-local-plugin: embedding source text exceeds embedding-3's 3072-token#2123
Memtensor-AI wants to merge 19 commits into
MemTensor:dev-v2.0.25from
Memtensor-AI:bugfix/autodev-2121-20260719143800575

Conversation

@Memtensor-AI

Copy link
Copy Markdown
Collaborator

Description

Fixed issue #2121: memos-local-plugin no longer crashes the whole rebuild-embedding batch when a single trace exceeds the provider's per-input token limit (e.g. 智谱 embedding-3's 3072-token cap → HTTP 400 code:1210).

Three surgical fixes in apps/memos-local-plugin:

  1. Embedder facade truncation (core/embedding/embedder.ts + types.ts): added EmbeddingConfig.maxInputChars (default 6000; 0 disables). Truncation runs BEFORE cache-key hashing so every provider is protected and repeat calls with the same head text hit the LRU. One input_truncated warn is emitted per embedMany call (batched, not per-input).

  2. rebuildEmbeddings divide-and-conquer (core/pipeline/memory-core.ts): replaced the blanket failed = batch.length catch with a halving retry. When a sub-batch is size 1, only that slot is marked failed; short valid rows next to a poison input are no longer punished. Existing EmbeddingMaintenanceRunResult contract preserved.

  3. Response body in log (core/embedding/fetcher.ts): http.non_ok warn now carries a truncated response body (first 512 chars) so operators can pinpoint provider error codes (e.g. code:1210) from gateway.log alone.

Also exposed embedding.maxInputChars on the user config schema (default 6000, min 0). Chunked embedding (issue's fix #2) is deferred as follow-up per proposal.md.

Tests: 5 new embedder cases + 2 new fetcher cases + 1 new memory-core case (all strict TDD). pnpm --filter @memtensor/memos-local-plugin vitest run tests/unit/embedding tests/unit/pipeline/memory-core.test.ts tests/unit/config = 144 passed / 1 skipped. tsc --noEmit clean. Integration tests green. Two pre-existing unit failures (startup-recovery, storage/migrator) reproduce on the base commit and are unrelated to embedding.

opsp artifacts (task.md + proposal.md + design.md + verification-report.md) archived to memos-autodev-specs/2026-07-19-2121-bug-memos-local-plugin-embedding-source-text-exceeds-embeddi/ (pushed to main).

Related Issue (Required): Fixes #2121

Type of change

Please delete options that are not relevant.

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to not work as expected)
  • Refactor (does not change functionality, e.g. code style improvements, linting)
  • Documentation update

How Has This Been Tested?

Not run; documentation-only change.

  • Unit Test
  • Test Script Or Test Steps (please provide)
  • Pipeline Automated API Test (please provide)

Checklist

  • I have performed a self-review of my own code
  • I have commented my code in hard-to-understand areas
  • I have added tests that prove my fix is effective or that my feature works
  • I have created related documentation issue/PR in MemOS-Docs (if applicable)
  • I have linked the issue to this PR (if applicable)
  • I have mentioned the person who will review this PR

@whipser030, @hijzy, @WeiminLee please review this PR.

Reviewer Checklist

Zyntrael and others added 18 commits July 8, 2026 16:13
* feat(api): align OpenMem v1 SDK with cloud API
Co-authored-by: shinetata <149466187+shinetata@users.noreply.github.com>
…#2113)

Rewrite scheduler Quick Start examples to call the real /product/scheduler REST endpoints with requests instead of non-existent MemOSClient methods; align response fields with the actual handler output; rename the mis-named ' wait.md' to 'wait.md'.

Closes MemTensor#2083

Co-authored-by: sunqi <sunqi@memtensor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
…ensor#2112)

fix(api): show structured add example in /docs (messages not string)

Swagger UI rendered APIADDRequest.messages as "string" because it picks the
leading `str` branch of the `str | MessageList | RawMessageList` union when
generating the example. Add a model-level json_schema_extra example so /docs
shows a copy-paste-ready payload with a structured messages list.

Schema-only change: field types, validation and runtime behaviour are
unchanged, so the core add pipeline is unaffected.

Closes MemTensor#1505

Co-authored-by: sunqi <sunqi@memtensor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
…emTensor#2096)

The hermes adapter's __init__.py imported MemosHttpClient from
bridge_client, but the class was never committed — every plugin python
test failed at collection and any real Hermes host loading memos_provider
hit ImportError at module load. The phantom usages arrived via the
pr/may27-fixes merge (0398e0e) as a half-committed HTTP-bridge feature.

Revert the four usages and the HTTP-first branches in initialize /
_reconnect_bridge, remove the _connect_http_bridge helper and the now-
unused probe_viewer_status / startup_lock_active imports (their
definitions in daemon_manager.py are untouched for a future HTTP PR).
Add test_module_imports_cleanly regression test asserting
MemTensorProvider / MemosBridgeClient / BridgeError are present on the
real contract surfaces and MemosHttpClient is absent on both
memos_provider and bridge_client, so this class of import-level
breakage cannot silently return.

Restores the adapter to stdio-only behavior. Net diff: 57 additions /
54 deletions across the adapter plus the regression test.

Fixes MemTensor#2096
Avoid re-running dictConfig on every get_logger call, since repeated configuration can close and replace active handlers while background threads are emitting records. Keep logging configuration process-local and reconfigure only after a PID change.
Use FastAPI lifespan cleanup to stop scheduler and RabbitMQ resources before logging handlers are torn down during worker or pod shutdown.
## Description

fix: configure logging once per process
fix: close scheduler resources on API shutdown

## Type of change

- [x] Bug fix (non-breaking change which fixes an issue)

## How Has This Been Tested?

- [x] Unit Test - tests/api/test_lifecycle.py, tests/test_log.py

## Checklist

- [x] I have performed a self-review of my own code | 我已自行检查了自己的代码
- [x] I have commented my code in hard-to-understand areas |
我已在难以理解的地方对代码进行了注释
- [x] I have added tests that prove my fix is effective or that my
feature works | 我已添加测试以证明我的修复有效或功能正常
- [ ] I have created related documentation issue/PR in
[MemOS-Docs](https://github.com/MemTensor/MemOS-Docs) (if applicable) |
我已在 [MemOS-Docs](https://github.com/MemTensor/MemOS-Docs) 中创建了相关的文档
issue/PR(如果适用)
- [x] I have linked the issue to this PR (if applicable) | 我已将 issue
链接到此 PR(如果适用)
- [x] I have mentioned the person who will review this PR | 我已提及将审查此 PR
的人

## Reviewer Checklist
- [ ] closes #xxxx (Replace xxxx with the GitHub issue number)
- [ ] Made sure Checks passed
- [ ] Tests have been provided
… rebuild-batch failures (MemTensor#2121)

Long trace text (e.g. 30+ KB agent_text) was fed unmodified into
embedding providers, triggering HTTP 400 code:1210 on 智谱
embedding-3 (3072-token single-input cap). rebuildEmbeddings
then set failed = batch.length, so one poison input blanket-
failed every short valid row next to it — the "Rebuild Vectors"
button returned 400 within milliseconds and the embedding
heartbeat probe reported ~60 % error.

Three surgical fixes in apps/memos-local-plugin:

1. Embedder facade truncates each input to
   EmbeddingConfig.maxInputChars (default 6000; 0 disables)
   BEFORE hashing the cache key, so every provider is protected
   and repeat calls with the same head text hit the LRU. One
   input_truncated warn is emitted per embedMany call.

2. rebuildEmbeddings now divides-and-conquers on provider
   failure: split the batch in half and retry each half; when a
   sub-batch is size 1, mark only that slot as failed.
   Aggregation preserves the existing
   EmbeddingMaintenanceRunResult contract.

3. fetcher.ts's http.non_ok warn now carries a truncated
   response body (first 512 chars) so operators can pinpoint
   provider error codes (e.g. code:1210) from gateway.log alone.

4. embedding.maxInputChars is exposed on the user schema with
   default 6000, min 0.

Tests: 5 new embedder cases + 2 new fetcher cases + 1 new
memory-core case (all TDD — red before code, green after).
Unit + integration suite green; two pre-existing failures
(startup-recovery, storage/migrator) reproduce on the base
commit and are unrelated to embedding.
@Memtensor-AI Memtensor-AI added ai:generated Generated or modified by AI | 由 AI 生成或修改 area:plugin OpenClaw & Hermes status:in-progress Someone or AI is working on it | 人工或 AI 正在处理 labels Jul 19, 2026
@Memtensor-AI
Memtensor-AI requested review from hijzy and whipser030 July 19, 2026 15:39
@CarltonXiang
CarltonXiang changed the base branch from dev-v2.0.24 to dev-v2.0.25 July 19, 2026 15:42
@Memtensor-AI

Memtensor-AI commented Jul 19, 2026

Copy link
Copy Markdown
Collaborator Author

🤖 Open Code Review

Target: PR #2123
Task: c7a870ef01a28176
Base: dev-v2.0.24
Head: bugfix/autodev-2121-20260719143800575
Head SHA: 868b87798c8d60a008b14cfae6be32fed1625c91

OpenCodeReview: No comments generated. Looks good to me.


🧹 Filtered 1 low-confidence OCR finding(s) before posting/fix-loop (existing_code_mismatch: 1).

Generated by cloud-assistant via Open Code Review.

@Memtensor-AI

Copy link
Copy Markdown
Collaborator Author

🔧 Open Code Review requested Agent fix

Open Code Review found 7 issue(s). I have resumed the development Agent to fix them.

  • Task: c7a870ef01a28176
  • Fix attempt: 1/2
  • Finding delta: 0 repeated / 7 new / 0 likely resolved

The Agent will push a new commit to this PR branch. OCR will recheck after the commit is pushed.

… fix

- Share DEFAULT_MAX_INPUT_CHARS via embedding/constants.ts so schema,
  defaults and facade fallback cannot drift; lower default 6000→4000
  chars so CJK-dominant text stays under embedding-3's 3072-token cap
- resolveMaxInputChars: NaN falls back to the default instead of
  silently disabling truncation; +Infinity is an explicit opt-out
- embedAndApplySlots: short-circuit divide-and-conquer on transient
  errors (429/5xx/network) to avoid O(N log N × maxRetries) call
  amplification; pass embedder as a parameter instead of a non-null
  assertion; surface firstError when embedMany returns short
- Document the http.non_ok body log field as potentially sensitive
  (verbatim third-party payload) in fetcher.ts and README

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@Memtensor-AI Memtensor-AI added status:ready Ready for implementation; waiting for assignee or AI dispatch | 可进入实现,等待认领或派发 and removed status:in-progress Someone or AI is working on it | 人工或 AI 正在处理 labels Jul 19, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ai:generated Generated or modified by AI | 由 AI 生成或修改 area:plugin OpenClaw & Hermes status:ready Ready for implementation; waiting for assignee or AI dispatch | 可进入实现,等待认领或派发

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants