Python: Bug: split_plaintext_paragraph / split_markdown_paragraph can return a chunk larger than max_tokens
Maintainers usually reply within 4 days
Assessment
- Difficulty
- 2/5
- Estimated time
- 1-3 hours
- Newbie friendliness
- 75/100
Research direction
Read python/semantic_kernel/text/text_chunker.py, especially _split_text_paragraph around the linked lines, and inspect tests/unit/text/test_text_chunker.py. Run the text chunker tests first; update the merge behavior and affected expected outputs so the final chunk is merged only when token_counter confirms it fits. Done means no returned chunk exceeds max_tokens and the relevant tests pass.
Written by the indexing model from the issue text.
Description
Describe the bug
split_plaintext_paragraph and split_markdown_paragraph can return a paragraph whose token count is above max_tokens.
At the end of _split_text_paragraph, a short last paragraph is merged into the previous one. The merge check counts words (len(paragraph.split(" "))) instead of calling token_counter:
A word is usually more than one token, so the merged paragraph can go over the limit even though the word count is under it. This matters when max_tokens is the embedding model's input limit.
To Reproduce
With the default token counter, using the input of the existing test_split_text_paragraph_evenly test:
from semantic_kernel.text import split_plaintext_paragraph
text = [
"This is a test of the emergency broadcast system. This is only a test.",
"We repeat, this is only a test. A unit test.",
"A small note. And another. And once again. Seriously, this is the end. We're finished. All set. Bye.",
"Done.",
]
chunks = split_plaintext_paragraph(text, 15)
print([len(c) // 4 for c in chunks]) # [12, 5, 11, 10, 16] -> last chunk is 16 tokens, limit is 15
With a real tokenizer (tiktoken, cl100k_base) passed as token_counter, on generated multi-line English text and limits from 64 to 512, 955 of 8000 runs (about 12%) returned an over-limit chunk. The worst one was 314 tokens for max_tokens=256.
Expected behavior
No returned paragraph is above max_tokens. The last paragraph should only be merged into the previous one if the merged text fits, measured with token_counter.
Platform
- Language: Python
- Source:
mainat cc8a15fa3 - OS: Windows 11, Python 3.12
Additional context
Eight existing unit tests in tests/unit/text/test_text_chunker.py expect an over-limit last chunk (for example 16 tokens with max_token_per_line = 15). A fix would change their expected output, so I wanted to raise it here first. I have a small fix with tests ready and I'm happy to open the PR.
- Dominant language
- C#
- Stars
- 28.6k
- Forks
- 4.8k
- Avg merge
- 2d 1h
- Merged PRs (30d)
- 20
Getting set up
Starts the project's dev container in your browser, under your own GitHub account.
- No Dockerfile or Docker Compose file
- Has a pull request template
- Read the contributing guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
More from microsoft/semantic-kernel
-
.Net: gpt-image-1 is the default image model in the .NET OpenAI connector, and OpenAI shuts it down on October 23Possibly taken @nightcityblade claimed this 4 days ago. Open.NET triage
Difficulty 2/5 1-3 hours Newbie friendliness 73/100
microsoft/semantic-kernel#14526 · 1 comment ·
Maintainers usually reply within 4 days
-
Python: VolatileMemoryStore.get_batch and get_nearest_matches ignore with_embeddings=False (deepcopy result is discarded)Possibly taken @VANDRANKI claimed this 6 days ago. Openpython triage
Difficulty 2/5 1-3 hours Newbie friendliness 84/100
microsoft/semantic-kernel#14522 ·
Maintainers usually reply within 4 days
-
Python: VolatileMemoryStore.get_nearest_match returns an un-awaited coroutine instead of a (MemoryRecord, score) tuplePossibly taken @VANDRANKI claimed this 6 days ago. Openpython triage
Difficulty 2/5 1-3 hours Newbie friendliness 88/100
microsoft/semantic-kernel#14521 ·
Maintainers usually reply within 4 days
-
.Net: Bug: BinaryContent does not decode the %xx escapes of a non-base64 data URIPossibly taken @Laurianti claimed this 6 days ago. Open.NET triage
Difficulty 2/5 1-3 hours Newbie friendliness 76/100
microsoft/semantic-kernel#14518 ·
Maintainers usually reply within 4 days
-
Python: FunctionCallContent.combine_arguments drops a streamed "{}" chunk, producing invalid JSON argumentsPossibly taken @VANDRANKI claimed this 7 days ago. Openpython triage
Difficulty 2/5 1-3 hours Newbie friendliness 82/100
microsoft/semantic-kernel#14512 · 2 comments ·
Maintainers usually reply within 4 days
All issues in microsoft/semantic-kernel
Similar issues
-
Bug pulumi/pulumi
Difficulty 2/5 1-3 hours Newbie friendliness 72/100
Maintainers usually reply within 1 day
-
Difficulty 2/5 1-3 hours Newbie friendliness 82/100
activescott/lessmsi#306 ·
-
Difficulty 2/5 1-3 hours Newbie friendliness 78/100
Maintainers usually reply within 1 day
-
HTML sitemap lists unpublished pagesPossibly taken @KrzysztofPajak claimed this today. Open
Difficulty 2/5 1-3 hours Newbie friendliness 82/100
grandnode/grandnode2#883 ·
Maintainers usually reply within 1 day
-
bug
Difficulty 2/5 1-3 hours Newbie friendliness 84/100
Maintainers usually reply within 1 day