1616 "Authorization" : f"Bearer { API_KEY } " ,
1717 "Content-Type" : "application/json" ,
1818 "Accept" : "text/event-stream" ,
19- "X-DashScope-SSE" : "enable" # 模拟 DashScope 协议头
19+ "X-DashScope-SSE" : "enable" , # 模拟 DashScope 协议头
2020}
2121
2222# --- TOOL DEFINITIONS ---
4343
4444# --- HELPERS ---
4545
46+
4647@dataclass
4748class SSEFrame :
4849 """Formal representation of a Server-Sent Event frame for validation."""
50+
4951 id : str
5052 output : Dict [str , Any ]
5153 usage : Dict [str , Any ]
5254 request_id : str
5355
56+
5457def parse_sse_stream (response : requests .Response ) -> Generator [SSEFrame , None , None ]:
5558 """Parses the raw SSE stream."""
5659 for line in response .iter_lines ():
@@ -61,20 +64,25 @@ def parse_sse_stream(response: requests.Response) -> Generator[SSEFrame, None, N
6164 try :
6265 data = json .loads (json_str )
6366 yield SSEFrame (
64- id = data .get ("output" , {}).get ("choices" , [{}])[0 ].get ("id" , "unknown" ),
67+ id = data .get ("output" , {})
68+ .get ("choices" , [{}])[0 ]
69+ .get ("id" , "unknown" ),
6570 output = data .get ("output" , {}),
6671 usage = data .get ("usage" , {}),
6772 request_id = data .get ("request_id" , "" ),
6873 )
6974 except json .JSONDecodeError :
7075 continue
7176
77+
7278def make_request (payload ):
7379 """Helper to send POST request."""
7480 return requests .post (GATEWAY_URL , headers = HEADERS , json = payload , stream = True )
7581
82+
7683# --- TEST SUITE ---
7784
85+
7886class TestParameterValidation :
7987 """
8088 对应表格中参数校验相关的错误用例 (4xx Error Codes)
@@ -88,16 +96,20 @@ def test_invalid_parameter_type_top_p(self):
8896 payload = {
8997 "model" : "pre-siliconflow/deepseek-v3" ,
9098 "input" : {"messages" : [{"role" : "user" , "content" : "你好" }]},
91- "parameters" : {"top_p" : "a" } # Invalid type
99+ "parameters" : {"top_p" : "a" }, # Invalid type
92100 }
93101 response = make_request (payload )
94102
95103 # 验证状态码不应为 500
96- assert response .status_code != 500 , "Should not return 500 for invalid parameter type"
104+ assert (
105+ response .status_code != 500
106+ ), "Should not return 500 for invalid parameter type"
97107 assert response .status_code == 400
98108
99109 data = response .json ()
100- assert "InvalidParameter" in data .get ("code" , "" ) or "InvalidParameter" in data .get ("message" , "" )
110+ assert "InvalidParameter" in data .get (
111+ "code" , ""
112+ ) or "InvalidParameter" in data .get ("message" , "" )
101113
102114 @pytest .mark .parametrize ("top_p_value" , [0 , 0.0 ])
103115 def test_invalid_parameter_range_top_p (self , top_p_value ):
@@ -108,7 +120,7 @@ def test_invalid_parameter_range_top_p(self, top_p_value):
108120 payload = {
109121 "model" : "pre-siliconflow/deepseek-v3.1" ,
110122 "input" : {"messages" : [{"role" : "user" , "content" : "你好" }]},
111- "parameters" : {"top_p" : top_p_value }
123+ "parameters" : {"top_p" : top_p_value },
112124 }
113125 response = make_request (payload )
114126
@@ -124,7 +136,7 @@ def test_invalid_parameter_range_temperature(self):
124136 payload = {
125137 "model" : "pre-siliconflow/deepseek-v3.1" ,
126138 "input" : {"messages" : [{"role" : "user" , "content" : "你好" }]},
127- "parameters" : {"temperature" : 2.1 }
139+ "parameters" : {"temperature" : 2.1 },
128140 }
129141 response = make_request (payload )
130142
@@ -146,7 +158,7 @@ def test_r1_usage_structure(self):
146158 payload = {
147159 "model" : "pre-siliconflow/deepseek-r1" ,
148160 "input" : {"messages" : [{"role" : "user" , "content" : "你好" }]},
149- "parameters" : {}
161+ "parameters" : {},
150162 }
151163 response = make_request (payload )
152164 assert response .status_code == 200
@@ -160,7 +172,9 @@ def test_r1_usage_structure(self):
160172 # 验证 output_tokens_details 存在
161173 assert output_details , "output_tokens_details missing"
162174 # 验证不包含 text_tokens (根据表格描述这是预期行为)
163- assert "text_tokens" not in output_details , "R1 usage should not contain text_tokens"
175+ assert (
176+ "text_tokens" not in output_details
177+ ), "R1 usage should not contain text_tokens"
164178 # 验证包含 reasoning_tokens
165179 assert "reasoning_tokens" in output_details
166180
@@ -172,7 +186,7 @@ def test_r1_enable_thinking_parameter_error(self):
172186 payload = {
173187 "model" : "pre-siliconflow/deepseek-r1" ,
174188 "input" : {"messages" : [{"role" : "user" , "content" : "你好" }]},
175- "parameters" : {"enable_thinking" : True }
189+ "parameters" : {"enable_thinking" : True },
176190 }
177191 response = make_request (payload )
178192
@@ -196,18 +210,18 @@ def test_prefix_completion_thinking_conflict(self):
196210 "input" : {
197211 "messages" : [
198212 {"role" : "user" , "content" : "你好" },
199- {"role" : "assistant" , "partial" : True , "content" : "你好,我是" }
213+ {"role" : "assistant" , "partial" : True , "content" : "你好,我是" },
200214 ]
201215 },
202- "parameters" : {
203- "enable_thinking" : True
204- }
216+ "parameters" : {"enable_thinking" : True },
205217 }
206218 response = make_request (payload )
207219
208220 assert response .status_code == 400
209221 data = response .json ()
210- assert "Partial mode is not supported when enable_thinking is true" in data .get ("message" , "" )
222+ assert "Partial mode is not supported when enable_thinking is true" in data .get (
223+ "message" , ""
224+ )
211225
212226 def test_history_with_tool_calls (self ):
213227 """
@@ -220,40 +234,37 @@ def test_history_with_tool_calls(self):
220234 "messages" : [
221235 {
222236 "role" : "system" ,
223- "content" : "你是一个为智能助手。请使用简洁、自然、适合朗读的中文回答"
224- },
225- {
226- "role" : "user" ,
227- "content" : "外部轴设置"
237+ "content" : "你是一个为智能助手。请使用简洁、自然、适合朗读的中文回答" ,
228238 },
239+ {"role" : "user" , "content" : "外部轴设置" },
229240 {
230241 "role" : "assistant" ,
231242 "tool_calls" : [
232243 {
233244 "function" : {
234- "arguments" : "{ \ " input_text\ " : \ " 外部轴设置\" }" ,
235- "name" : "KB20250625001"
245+ "arguments" : '{ "input_text": "外部轴设置"}' ,
246+ "name" : "KB20250625001" ,
236247 },
237248 "id" : "call_6478091069c2448b83f38e" ,
238- "type" : "function"
249+ "type" : "function" ,
239250 }
240- ]
251+ ],
241252 },
242253 {
243254 "role" : "tool" ,
244255 "content" : "界面用于用户进行快速配置。" ,
245- "tool_call_id" : "call_6478091069c2448b83f38e"
246- }
256+ "tool_call_id" : "call_6478091069c2448b83f38e" ,
257+ },
247258 ]
248259 },
249- "parameters" : {
250- "enable_thinking" : True
251- }
260+ "parameters" : {"enable_thinking" : True },
252261 }
253262 response = make_request (payload )
254263
255264 # 核心验证:不能崩 (500)
256- assert response .status_code != 500 , "Server returned 500 for history with tool calls"
265+ assert (
266+ response .status_code != 500
267+ ), "Server returned 500 for history with tool calls"
257268 assert response .status_code == 200
258269
259270 def test_r1_tool_call_format_wrapping (self ):
@@ -265,13 +276,18 @@ def test_r1_tool_call_format_wrapping(self):
265276 payload = {
266277 "model" : "pre-siliconflow/deepseek-r1" ,
267278 "input" : {
268- "messages" : [{"role" : "user" , "content" : "What is the weather like in Boston?" }]
279+ "messages" : [
280+ {"role" : "user" , "content" : "What is the weather like in Boston?" }
281+ ]
269282 },
270283 "parameters" : {
271284 "result_format" : "message" ,
272- "tool_choice" : {"type" : "function" , "function" : {"name" : "get_current_weather" }}, # 修正后的 tool_choice 格式
273- "tools" : TOOL_VECTOR_WEATHER
274- }
285+ "tool_choice" : {
286+ "type" : "function" ,
287+ "function" : {"name" : "get_current_weather" },
288+ }, # 修正后的 tool_choice 格式
289+ "tools" : TOOL_VECTOR_WEATHER ,
290+ },
275291 }
276292
277293 # 注意:CSV中提到的错误是 `tool_choice` 格式问题导致的 400 被包了一层 500
0 commit comments