Skip to content

Commit 083ec77

Browse files
Merge pull request #2769 from Osamaali313/fix/rag-truncate-context-char-boundary
fix(rag): avoid panic when truncating context on a UTF-8 char boundary
2 parents a507201 + b2e6298 commit 083ec77

1 file changed

Lines changed: 24 additions & 2 deletions

File tree

  • src/praisonai-rust/praisonai/src/rag

src/praisonai-rust/praisonai/src/rag/mod.rs

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -549,7 +549,13 @@ impl RAG {
549549
return context.to_string();
550550
}
551551

552-
format!("{}...", &context[..char_limit])
552+
// `char_limit` is a byte count; walk back to the nearest char boundary
553+
// so we never slice through a multi-byte UTF-8 character (would panic).
554+
let mut end = char_limit.min(context.len());
555+
while end > 0 && !context.is_char_boundary(end) {
556+
end -= 1;
557+
}
558+
format!("{}...", &context[..end])
553559
}
554560
}
555561

@@ -616,7 +622,13 @@ pub fn truncate_context(context: &str, max_tokens: usize) -> String {
616622
return context.to_string();
617623
}
618624

619-
format!("{}...", &context[..char_limit])
625+
// `char_limit` is a byte count; walk back to the nearest char boundary so
626+
// we never slice through a multi-byte UTF-8 character (which would panic).
627+
let mut end = char_limit.min(context.len());
628+
while end > 0 && !context.is_char_boundary(end) {
629+
end -= 1;
630+
}
631+
format!("{}...", &context[..end])
620632
}
621633

622634
/// Deduplicate chunks by content similarity.
@@ -760,6 +772,16 @@ mod tests {
760772
assert!(truncated.ends_with("..."));
761773
}
762774

775+
#[test]
776+
fn test_truncate_context_multibyte_no_panic() {
777+
// A byte-based char_limit can land inside a multi-byte character;
778+
// truncation must not panic and must cut on a char boundary.
779+
let text = "日本語テキストです".repeat(50); // multi-byte, well over the limit
780+
let truncated = truncate_context(&text, 1);
781+
assert!(truncated.ends_with("..."));
782+
assert!(truncated.len() < text.len());
783+
}
784+
763785
#[test]
764786
fn test_deduplicate_chunks() {
765787
let chunks = vec![

0 commit comments

Comments
 (0)