Skip to content

Fix #2115: fix: SimpleTextSplitter fallback 在文件解析链路中报错:缺少 protect_urls#2116

Open
Memtensor-AI wants to merge 2 commits into
MemTensor:dev-v2.0.24from
Memtensor-AI:bugfix/autodev-2115-20260716073650486
Open

Fix #2115: fix: SimpleTextSplitter fallback 在文件解析链路中报错:缺少 protect_urls#2116
Memtensor-AI wants to merge 2 commits into
MemTensor:dev-v2.0.24from
Memtensor-AI:bugfix/autodev-2115-20260716073650486

Conversation

@Memtensor-AI

Copy link
Copy Markdown
Collaborator

Description

Fixes issue #2115: SimpleTextSplitter fallback in the multi-modal file-parsing pipeline was raising AttributeError: 'SimpleTextSplitter' object has no attribute 'protect_urls'. Root cause: SimpleTextSplitter._simple_split_text() calls self.protect_urls / self.restore_urls, but those helpers live on BaseChunker and SimpleTextSplitter does not inherit from it. On ACK (where langchain_text_splitters is missing and the fallback is actually exercised) this produced ~5.8k noisy log rows and silently degraded chunking to a single-chunk pass-through.

The fix extracts protect_urls / restore_urls into a small URLProtectionMixin in src/memos/chunkers/base.py; BaseChunker now inherits it (behavioural no-op — same public API), and SimpleTextSplitter in src/memos/chunkers/simple_chunker.py also inherits it, so the two paths share one URL regex and one placeholder scheme. SimpleTextSplitter's constructor signature and chunk() -> list[str] return type are unchanged; no factory / config / OpenAPI changes are required.

Verification: 7 new regression tests in tests/chunkers/test_simple_chunker.py (short/long input with URL, empty / whitespace input, no-URL text, parametrised chunk sizes) — all 7 failed before the fix with the exact AttributeError, all 7 pass after. Broader pytest tests/chunkers/ tests/mem_reader/ → 63 pass; the 2 unrelated failures (test_doc_local_file, test_doc_mixed) fail identically on the pristine branch with the change stashed and are caused by the sandbox missing markitdown[all]. ruff check + ruff format --check are green on all 3 changed files.

Working branch pushed to origin; opsp task + verification report archived to memos-autodev-specs main. Ready for reviewer @WeiminLee.

Related Issue (Required): Fixes #2115

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

@WeiminLee please review this PR.

Reviewer Checklist

)

`SimpleTextSplitter._simple_split_text()` called `self.protect_urls` and
`self.restore_urls`, methods defined only on `BaseChunker`. Since
`SimpleTextSplitter` does not inherit `BaseChunker`, every call raised
`AttributeError: 'SimpleTextSplitter' object has no attribute
'protect_urls'`. The multi-modal file-parsing pipeline swallowed the
error and fell back to returning the whole text as a single chunk,
producing ~5.8k noisy log rows on ACK where langchain_text_splitters is
missing and the fallback branch is actually exercised.

Extract the URL protect/restore helpers into a small `URLProtectionMixin`
in `chunkers/base.py`; have both `BaseChunker` and `SimpleTextSplitter`
inherit it. This preserves BaseChunker's public API (mixin methods are
inherited transparently), keeps SimpleTextSplitter's constructor and
return type unchanged, and shares a single URL regex between the two
paths.

Add regression tests in tests/chunkers/test_simple_chunker.py covering
short/long input, empty input, no-URL text, and parametrised
(chunk_size, overlap) combinations to ensure the fallback never raises
again.
@Memtensor-AI Memtensor-AI added ai:generated Generated or modified by AI | 由 AI 生成或修改 area:core MOS 编排层 / 框架底座 / 跨模块问题 status:in-progress Someone or AI is working on it | 人工或 AI 正在处理 labels Jul 16, 2026
@Memtensor-AI
Memtensor-AI requested a review from WeiminLee July 16, 2026 08:02
@Memtensor-AI

Memtensor-AI commented Jul 16, 2026

Copy link
Copy Markdown
Collaborator Author

🤖 Open Code Review

Target: PR #2116
Task: e062b03201f62d58
Base: dev-v2.0.24
Head: bugfix/autodev-2115-20260716073650486
Head SHA: e2b5e7423ac4bce7ee462f242dcf56043d109e09

OpenCodeReview: No comments generated. Looks good to me.

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 1 issue(s). I have resumed the development Agent to fix them.

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

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

Address OCR review on MemTensor#2116: the placeholder-leak assertion in
tests/chunkers/test_simple_chunker.py hardcoded the string `'__URL_'`,
which duplicates an implementation detail of
`URLProtectionMixin.protect_urls` (formatted as
`f'__URL_{len(url_map)}__'`). If the prefix ever changed in `base.py`,
the assertion would silently keep passing while no longer catching real
placeholder leaks.

Expose the prefix as a class-level constant
`URLProtectionMixin._URL_PLACEHOLDER_PREFIX = "__URL_"`, use it inside
`protect_urls`, and import it in the test so the two paths stay in sync
automatically.

No behavior change: placeholders keep the same textual form
(`__URL_<n>__`), so both the current base chunker and the fallback
`SimpleTextSplitter` produce identical output to before.
@Memtensor-AI

Copy link
Copy Markdown
Collaborator Author

✅ Automated Test Results: PASSED

All tests passed (69/69 executed). memos_github_open_source/smoke: 1/1, memos_local_plugin/unit: 23/23, memos_python_core/changed-repo-python: 45/45. Duration: 12s [advisory, non-gating] AI-generated tests on branch test/auto-gen-e062b03201f62d58-20260716160757: 102/103 passed, 1 failed — these do NOT affect the PR verdict; review the branch manually.

Branch: bugfix/autodev-2115-20260716073650486

@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 16, 2026

@WeiminLee WeiminLee left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM. Agent addressed the OCR finding by extracting _URL_PLACEHOLDER_PREFIXto URLProtectionMixin, tests aligned correctly. CI/AutoTest all passed, ready to merge.

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:core MOS 编排层 / 框架底座 / 跨模块问题 status:ready Ready for implementation; waiting for assignee or AI dispatch | 可进入实现,等待认领或派发

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants