ForcePilot/backend/package/yuxi/channels/adapters/zalo_user/chunking.py
Kris 9285da5c55 feat(zalo-user): 实现完整的Zalo用户频道适配器
新增了Zalo用户频道的完整适配器实现,包括:
- 基础的适配器初始化与导出结构
- 群组同步与成员获取功能
- 请求限流与退避重试机制
- 健康检查与状态探针
- 消息反应/表情处理工具
- 贴纸缓存与消息去重功能
- 消息ID格式化与追踪
- TTS语音合成支持
- 消息发送权限校验
- 长文本分块发送
- 操作审批流程
- 常量配置与国际化支持
- 图像视觉分析功能
- 贴纸消息处理
- 登录与配置向导
- 群组上下文缓存
- 网关连接管理
- 配置Schema校验
- 状态问题与安全审计
- 内联按钮与交互组件
- 交互式回调分发
- 联系人与群组目录管理
- 富媒体卡片消息支持
2026-05-12 00:53:13 +08:00

64 lines
1.8 KiB
Python

from __future__ import annotations
import re
ZALO_MAX_TEXT_LENGTH = 2000
_SENTENCE_BOUNDARY = re.compile(r"[。!?.!?\n]")
def chunk_text(text: str, limit: int = ZALO_MAX_TEXT_LENGTH) -> list[str]:
if len(text) <= limit:
return [text]
chunks: list[str] = []
paragraphs = text.split("\n\n")
current = ""
for para in paragraphs:
if len(current) + len(para) + 2 <= limit:
current = f"{current}\n\n{para}" if current else para
else:
if current:
chunks.append(current)
if len(para) > limit:
sub_chunks = _chunk_long_paragraph(para, limit)
if sub_chunks:
if sub_chunks[-1]:
current = sub_chunks.pop()
else:
sub_chunks.pop()
current = ""
chunks.extend(sub_chunks)
else:
current = ""
else:
current = para
if current:
chunks.append(current)
return chunks or [text]
def _chunk_long_paragraph(text: str, limit: int) -> list[str]:
chunks: list[str] = []
remaining = text
while len(remaining) > limit:
split_at = _find_split_point(remaining, limit)
chunks.append(remaining[:split_at].rstrip())
remaining = remaining[split_at:].lstrip()
chunks.append(remaining)
return chunks
def _find_split_point(text: str, limit: int) -> int:
candidates = [m.start() for m in _SENTENCE_BOUNDARY.finditer(text, limit // 2, limit)]
if candidates:
return candidates[-1] + 1
newline = text.rfind("\n", limit // 2, limit)
if newline != -1:
return newline + 1
space = text.rfind(" ", limit // 2, limit)
if space != -1:
return space + 1
return limit