diff --git a/rag/chunk_handler.py b/rag/chunk_handler.py index 17dd4a6..086e45a 100644 --- a/rag/chunk_handler.py +++ b/rag/chunk_handler.py @@ -4,6 +4,7 @@ Think标签过滤器模块 - 支持LlamaIndex流式响应 from typing import Tuple, Any, Union, Optional import json +import re class OptimizedDeltaThinkFilter: """ @@ -85,7 +86,6 @@ class OptimizedDeltaThinkFilter: # 检查是否包含常见字段 if 'text=' in str_repr or 'delta=' in str_repr or 'content=' in str_repr: # 尝试提取引号内的内容 - import re text_match = re.search(r'text=[\'"](.*?)[\'"]', str_repr) if text_match: return text_match.group(1) @@ -143,54 +143,137 @@ class OptimizedDeltaThinkFilter: delta_text = self._extract_llamaindex_content(chunk) if not delta_text: - # 即使没有文本内容,返回当前状态 return "", self.output_text, False - + # 添加到buffer self.buffer += delta_text output_delta = "" + # 使用状态机处理 i = 0 while i < len(self.buffer): if not self.in_think: - # 不在think标签内,查找开始标签 - start = self.buffer.find('', i) - if start == -1: - # 没有think标签,剩余都是有效文本 - valid_text = self.buffer[i:] - output_delta += valid_text - self.output_text += valid_text - i = len(self.buffer) + # 寻找开始标签 + start_idx = self.buffer.lower().find('', i) + if start_idx == -1: + # FIXED: 检查是否有孤立的结束标签 + end_idx = self.buffer.lower().find('', i) + if end_idx != -1: + # FIXED: 如果发现孤立结束标签,说明之前的内容都是think内容,应该丢弃 + # 直接跳过结束标签之前的所有内容 + # print(f"DEBUG: 发现孤立结束标签,丢弃 {self.buffer[i:end_idx]}") + i = end_idx + len('') # 只跳过结束标签 + continue + else: + # 没有think标签,剩余都是有效文本 + valid_text = self.buffer[i:] + output_delta += valid_text + self.output_text += valid_text + i = len(self.buffer) else: # 输出think标签前的部分 - valid_before = self.buffer[i:start] + valid_before = self.buffer[i:start_idx] output_delta += valid_before self.output_text += valid_before # 进入think模式 self.in_think = True - i = start + len('') + i = start_idx + len('') # 处理立即闭合的标签 - if self.buffer.find('', i) == i: + if self.buffer.lower().find('', i) == i: i += len('') self.in_think = False else: # 在think标签内,查找结束标签 - end = self.buffer.find('', i) - if end == -1: + end_idx = self.buffer.lower().find('', i) + if end_idx == -1: # 结束标签还没到,跳过所有内容 i = len(self.buffer) else: # 找到结束标签 self.in_think = False - i = end + len('') + i = end_idx + len('') # 清理已处理的buffer self.buffer = self.buffer[i:] if i < len(self.buffer) else "" has_output = len(output_delta) > 0 return output_delta, self.output_text, has_output + + + def process_delta_robust(self, chunk: Any) -> Tuple[str, str, bool]: + """ + 更健壮的处理方法,使用正则表达式 + + Args: + chunk: LlamaIndex流式chunk + + Returns: + Tuple[str, str, bool]: 处理结果 + """ + # 提取文本 + delta_text = self._extract_llamaindex_content(chunk) + + if not delta_text: + return "", self.output_text, False + + # 添加到buffer + self.buffer += delta_text + + output_delta = "" + processed_text = "" + + # 状态机处理 + while True: + if not self.in_think: + # 寻找开始标签 + start_match = re.search(r'', self.buffer, re.IGNORECASE) + if not start_match: + # FIXED: 检查是否有孤立的结束标签 + end_match = re.search(r'', self.buffer, re.IGNORECASE) + if end_match: + # FIXED: 如果发现孤立结束标签,说明之前的内容都是think内容,应该丢弃 + # 只移除结束标签,之前的内容已在上个chunk中被跳过 + end_pos = end_match.start() + # print(f"DEBUG: 发现孤立结束标签,位置 {end_pos}") + self.buffer = self.buffer[end_pos + len(''):] + continue + else: + # 既没有开始也没有结束标签,全部输出 + processed_text = self.buffer + self.buffer = "" + break + + # 输出开始标签之前的内容 + start_pos = start_match.start() + output_before = self.buffer[:start_pos] + processed_text += output_before + + # 移动buffer + self.buffer = self.buffer[start_pos + len(''):] + self.in_think = True + else: + # 在think标签内,寻找结束标签 + end_match = re.search(r'', self.buffer, re.IGNORECASE) + if not end_match: + # 结束标签不在这个buffer中 + # 清空buffer(think内容),等待下一个chunk + self.buffer = "" + break + + # 找到结束标签 + end_pos = end_match.start() + # 跳过think内容 + self.buffer = self.buffer[end_pos + len(''):] + self.in_think = False + + # 更新输出 + output_delta = processed_text + self.output_text += processed_text + + has_output = len(output_delta) > 0 + return output_delta, self.output_text, has_output def process_with_metadata(self, chunk: Any) -> dict: """ @@ -206,7 +289,7 @@ class OptimizedDeltaThinkFilter: original_content = self._extract_llamaindex_content(chunk) # 处理内容 - delta_output, full_text, has_output = self.process_delta(original_content) + delta_output, full_text, has_output = self.process_delta_robust(original_content) return { "delta": delta_output, diff --git a/rag/rag_engine.py b/rag/rag_engine.py index 039961d..d2e7a8b 100644 --- a/rag/rag_engine.py +++ b/rag/rag_engine.py @@ -259,7 +259,7 @@ class RAGEngine: async for chunk in stream_response: # 提取文本内容 # text_chunk = self.extract_text_from_chunk(chunk) - delta, full_text, has_output = think_filter.process_delta(chunk) + delta, full_text, has_output = think_filter.process_delta_robust(chunk) if delta is not None: full_response += delta