File size: 8,298 Bytes
fd21f34
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
#!/usr/bin/env python3
"""
测试 done 阶段处理
"""

import sys
import os
sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))

from app.utils.sse_tool_handler import SSEToolHandler
import json

def test_done_phase_handling():
    """测试 done 阶段的处理"""
    
    handler = SSEToolHandler("test-model", stream=True)
    
    print("🧪 测试 done 阶段处理\n")
    
    # 模拟完整的对话流程
    test_chunks = [
        # 回答阶段
        {
            "phase": "answer",
            "delta_content": "这是回答内容",
            "edit_content": ""
        },
        # 完成阶段
        {
            "phase": "done",
            "done": True,
            "delta_content": "",
            "usage": {
                "prompt_tokens": 100,
                "completion_tokens": 50,
                "total_tokens": 150
            }
        }
    ]
    
    output_chunks = []
    
    for i, chunk in enumerate(test_chunks, 1):
        print(f"处理块 {i}: phase={chunk['phase']}")
        
        results = list(handler.process_sse_chunk(chunk))
        output_chunks.extend(results)
        
        print(f"  输出数量: {len(results)}")
        for j, result in enumerate(results):
            if result.strip() == "data: [DONE]":
                print(f"  输出 {j+1}: [DONE] 标记")
            else:
                print(f"  输出 {j+1}: {result[:80]}{'...' if len(result) > 80 else ''}")
        print()
    
    print(f"📊 测试结果:")
    print(f"  总输出块数量: {len(output_chunks)}")
    
    # 验证输出内容
    has_content = False
    has_final_chunk = False
    has_done_marker = False
    has_usage = False
    
    for output in output_chunks:
        if output.startswith("data: "):
            json_str = output[6:].strip()
            if json_str == "[DONE]":
                has_done_marker = True
                print("  ✅ 找到 [DONE] 标记")
            elif json_str:
                try:
                    data = json.loads(json_str)
                    if "choices" in data and data["choices"]:
                        delta = data["choices"][0].get("delta", {})
                        content = delta.get("content", "")
                        finish_reason = data["choices"][0].get("finish_reason")
                        
                        if content:
                            has_content = True
                            print(f"  ✅ 找到内容: '{content}'")
                        
                        if finish_reason == "stop":
                            has_final_chunk = True
                            print("  ✅ 找到最终完成块")
                        
                        if "usage" in data:
                            has_usage = True
                            print(f"  ✅ 找到 usage 信息: {data['usage']}")
                            
                except json.JSONDecodeError as e:
                    print(f"  ❌ JSON 解析错误: {e}")
    
    # 验证结果
    success = has_content and has_final_chunk and has_done_marker
    
    print(f"\n📋 验证结果:")
    print(f"  包含回答内容: {'✅' if has_content else '❌'}")
    print(f"  包含最终完成块: {'✅' if has_final_chunk else '❌'}")
    print(f"  包含 [DONE] 标记: {'✅' if has_done_marker else '❌'}")
    print(f"  包含 usage 信息: {'✅' if has_usage else '❌'}")
    
    if success:
        print("\n✅ done 阶段处理测试通过!")
        return True
    else:
        print("\n❌ done 阶段处理测试失败!")
        return False

def test_done_phase_with_tool_call():
    """测试带工具调用的 done 阶段处理"""
    
    handler = SSEToolHandler("test-model", stream=True)
    
    print("🧪 测试带工具调用的 done 阶段处理\n")
    
    # 模拟工具调用 + 回答 + 完成的流程
    test_chunks = [
        # 工具调用开始
        {
            "phase": "tool_call",
            "edit_content": '<glm_block view="">{"type": "mcp", "data": {"metadata": {"id": "call_test", "name": "test_tool", "arguments": "{}", "result": "", "display_result": "", "duration": "...", "status": "completed", "is_error": false, "mcp_server": {"name": "mcp-server"}}, "thought": null, "ppt": null, "browser": null}}</glm_block>',
            "edit_index": 100
        },
        # 工具调用结束
        {
            "phase": "other",
            "edit_content": 'null, "display_result": "", "duration": "...", "status": "completed", "is_error": false, "mcp_server": {"name": "mcp-server"}}, "thought": null, "ppt": null, "browser": null}}</glm_block>',
            "edit_index": 200
        },
        # 回答阶段
        {
            "phase": "answer",
            "delta_content": "工具调用完成,这是回答。",
            "edit_content": ""
        },
        # 完成阶段
        {
            "phase": "done",
            "done": True,
            "delta_content": ""
        }
    ]
    
    output_chunks = []
    
    for i, chunk in enumerate(test_chunks, 1):
        print(f"处理块 {i}: phase={chunk['phase']}")
        
        results = list(handler.process_sse_chunk(chunk))
        output_chunks.extend(results)
        
        print(f"  输出数量: {len(results)}")
        print()
    
    # 检查是否有工具调用、回答内容和完成标记
    has_tool_call = any("tool_calls" in output for output in output_chunks)
    has_answer_content = any("工具调用完成" in output for output in output_chunks)
    has_done_marker = any(output.strip() == "data: [DONE]" for output in output_chunks)
    
    print(f"📊 混合流程测试结果:")
    print(f"  包含工具调用: {'✅' if has_tool_call else '❌'}")
    print(f"  包含回答内容: {'✅' if has_answer_content else '❌'}")
    print(f"  包含 [DONE] 标记: {'✅' if has_done_marker else '❌'}")
    
    success = has_tool_call and has_answer_content and has_done_marker
    
    if success:
        print("\n✅ 混合流程 done 阶段测试通过!")
        return True
    else:
        print("\n❌ 混合流程 done 阶段测试失败!")
        return False

def test_done_phase_warning_fix():
    """测试 done 阶段不再产生警告"""
    
    handler = SSEToolHandler("test-model", stream=True)
    
    print("🧪 测试 done 阶段警告修复\n")
    
    # 模拟 done 阶段
    chunk = {
        "phase": "done",
        "done": True,
        "delta_content": ""
    }
    
    print("处理 done 阶段块...")
    
    # 捕获日志输出(这里我们主要检查是否有异常)
    try:
        results = list(handler.process_sse_chunk(chunk))
        print(f"  成功处理,输出 {len(results)} 个块")
        
        # 检查是否有 [DONE] 标记
        has_done = any(output.strip() == "data: [DONE]" for output in results)
        print(f"  包含 [DONE] 标记: {'✅' if has_done else '❌'}")
        
        print("\n✅ done 阶段不再产生警告!")
        return True
        
    except Exception as e:
        print(f"\n❌ 处理 done 阶段时出错: {e}")
        return False

if __name__ == "__main__":
    print("🔧 测试 done 阶段处理\n")
    
    test1_success = test_done_phase_handling()
    print("\n" + "="*50 + "\n")
    test2_success = test_done_phase_with_tool_call()
    print("\n" + "="*50 + "\n")
    test3_success = test_done_phase_warning_fix()
    
    print("\n" + "="*50)
    print("🎯 总结:")
    print(f"  done 阶段基本处理: {'✅ 通过' if test1_success else '❌ 失败'}")
    print(f"  done 阶段混合流程: {'✅ 通过' if test2_success else '❌ 失败'}")
    print(f"  done 阶段警告修复: {'✅ 通过' if test3_success else '❌ 失败'}")
    
    if test1_success and test2_success and test3_success:
        print("\n🎉 所有测试通过!done 阶段处理完善!")
        print("\n💡 修复效果:")
        print("  - 不再显示 '未知的 SSE 阶段: done' 警告")
        print("  - 正确处理对话完成流程")
        print("  - 自动刷新缓冲区和完成工具调用")
        print("  - 发送标准的 OpenAI 完成标记")
    else:
        print("\n❌ 部分测试失败,需要进一步调试")