From 02bde14d52f85fa4aff7530cc411a29ff0b2001c Mon Sep 17 00:00:00 2001 From: liuwei Date: Tue, 7 Apr 2026 16:48:00 +0800 Subject: [PATCH] improve xiaoniu reply chunk splitting --- plugins/ai_auto_response/main.py | 40 +++++++++++++++++++++++++------- 1 file changed, 31 insertions(+), 9 deletions(-) diff --git a/plugins/ai_auto_response/main.py b/plugins/ai_auto_response/main.py index 629cf6f..9bca941 100644 --- a/plugins/ai_auto_response/main.py +++ b/plugins/ai_auto_response/main.py @@ -608,7 +608,7 @@ class AIAutoResponsePlugin(MessagePluginInterface): first = parts[0].strip() if parts and parts[0].strip() else text.strip() if len(first) <= limit: return first - clipped = first[:limit].rstrip(",,、;;::") + clipped = AIAutoResponsePlugin._smart_clip(first, limit) return clipped @staticmethod @@ -616,18 +616,40 @@ class AIAutoResponsePlugin(MessagePluginInterface): parts = [item.strip() for item in re.split(r"(?<=[。!?!?;;])", text) if item.strip()] if not parts: short = text.strip() - return [short[:char_limit].rstrip(",,、;;::").strip()] if short else [] + clipped = AIAutoResponsePlugin._smart_clip(short, char_limit) + remainder = short[len(clipped):].strip(",,、;;:: ") + return [item for item in [clipped, AIAutoResponsePlugin._smart_clip(remainder, char_limit)] if item][:chunk_limit] if short else [] chunks: List[str] = [] for part in parts[:sentence_limit]: - current = part - if len(current) > char_limit: - current = current[:char_limit].rstrip(",,、;;::") - if current: - chunks.append(current.strip()) - if len(chunks) >= chunk_limit: + current = part.strip() + while current and len(chunks) < chunk_limit: + if len(current) <= char_limit: + chunks.append(current.strip()) + break + clipped = AIAutoResponsePlugin._smart_clip(current, char_limit) + if not clipped: + clipped = current[:char_limit].rstrip(",,、;;:: ").strip() + if clipped: + chunks.append(clipped) + current = current[len(clipped):].strip(",,、;;:: ") + return chunks[:chunk_limit] or [AIAutoResponsePlugin._smart_clip(text, char_limit)] + + @staticmethod + def _smart_clip(text: str, limit: int) -> str: + text = str(text or "").strip() + if len(text) <= limit: + return text + window = text[:limit] + punctuation = ",,、;;::。!?!?))】]」』 " + split_at = -1 + for idx in range(len(window) - 1, max(len(window) - 10, 0) - 1, -1): + if window[idx] in punctuation: + split_at = idx break - return chunks[:chunk_limit] or [text[:char_limit].strip()] + if split_at >= 0: + return window[:split_at].rstrip(",,、;;::。!?!? ").strip() + return window.rstrip(",,、;;:: ").strip() def _sync_member_memory(self, room_id: str, sender: str, sender_name: str, member_context: Dict) -> None: if not member_context: