feat: add multi-space support with MicroHERO ZeroGPU default and auto-detection
This commit is contained in:
+127
-1
@@ -232,7 +232,7 @@ func TestQwenServiceChatMock(t *testing.T) {
|
||||
}))
|
||||
defer mockServer.Close()
|
||||
|
||||
svc := NewQwenService(mockServer.URL, "Qwen/Qwen3.8-Flash-Next", "", "", "", "", true)
|
||||
svc := NewQwenService(mockServer.URL, "Qwen/Qwen3.8-Flash-Next", "chat_response", "", "", "", "", true)
|
||||
|
||||
// 1. Test Non-streaming completion
|
||||
rec := httptest.NewRecorder()
|
||||
@@ -319,3 +319,129 @@ func TestQwenServiceChatMock(t *testing.T) {
|
||||
t.Fatalf("expected streamed content, got %q", receivedContent.String())
|
||||
}
|
||||
}
|
||||
|
||||
func TestParseAssistantTextDirectString(t *testing.T) {
|
||||
dataJSON := `["Step-by-step reasoning\n</think>\n\nFinal answer here", null]`
|
||||
text, ok := parseAssistantText(dataJSON)
|
||||
if !ok {
|
||||
t.Fatalf("expected successful parse of direct string assistant text")
|
||||
}
|
||||
if text != "Step-by-step reasoning\n</think>\n\nFinal answer here" {
|
||||
t.Fatalf("unexpected text: %q", text)
|
||||
}
|
||||
|
||||
reasoning, content := SeparateReasoningAndContent(text)
|
||||
if reasoning != "Step-by-step reasoning" {
|
||||
t.Fatalf("unexpected reasoning: %q", reasoning)
|
||||
}
|
||||
if content != "Final answer here" {
|
||||
t.Fatalf("unexpected content: %q", content)
|
||||
}
|
||||
}
|
||||
|
||||
func TestQwenServiceChatRespondMock(t *testing.T) {
|
||||
mockServer := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
if r.URL.Path == "/gradio_api/call/respond" && r.Method == http.MethodPost {
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
w.Write([]byte(`{"event_id": "respond_event_456"}`))
|
||||
return
|
||||
}
|
||||
|
||||
if r.URL.Path == "/gradio_api/call/respond/respond_event_456" && r.Method == http.MethodGet {
|
||||
w.Header().Set("Content-Type", "text/event-stream")
|
||||
flusher, _ := w.(http.Flusher)
|
||||
|
||||
chunk := `event: complete` + "\n" +
|
||||
`data: ["Analyzing the problem.\n</think>\n\nThe solution is 42.", null]` + "\n\n"
|
||||
w.Write([]byte(chunk))
|
||||
flusher.Flush()
|
||||
return
|
||||
}
|
||||
|
||||
http.NotFound(w, r)
|
||||
}))
|
||||
defer mockServer.Close()
|
||||
|
||||
svc := NewQwenService(mockServer.URL, "Qwen/Qwen3.8-27B-Uncensored", "respond", "", "", "", "", true)
|
||||
|
||||
// Non-streaming test
|
||||
rec := httptest.NewRecorder()
|
||||
req := ChatCompletionRequest{
|
||||
Model: "qwen3.8-27b",
|
||||
Messages: []ChatMessage{
|
||||
{Role: "user", Content: "What is the answer?"},
|
||||
},
|
||||
Stream: false,
|
||||
}
|
||||
|
||||
err := svc.Chat(rec, nil, req)
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error in respond non-streaming: %v", err)
|
||||
}
|
||||
if rec.Code != http.StatusOK {
|
||||
t.Fatalf("expected HTTP 200, got %d", rec.Code)
|
||||
}
|
||||
|
||||
var resp ChatCompletionResponse
|
||||
if err := json.NewDecoder(rec.Body).Decode(&resp); err != nil {
|
||||
t.Fatalf("failed to decode response: %v", err)
|
||||
}
|
||||
if resp.Choices[0].Message.Content != "The solution is 42." {
|
||||
t.Fatalf("unexpected content: %v", resp.Choices[0].Message.Content)
|
||||
}
|
||||
if resp.Choices[0].Message.ReasoningContent != "Analyzing the problem." {
|
||||
t.Fatalf("unexpected reasoning: %v", resp.Choices[0].Message.ReasoningContent)
|
||||
}
|
||||
|
||||
// Streaming test
|
||||
recStream := httptest.NewRecorder()
|
||||
reqStream := ChatCompletionRequest{
|
||||
Model: "qwen3.8-27b",
|
||||
Messages: []ChatMessage{
|
||||
{Role: "user", Content: "What is the answer?"},
|
||||
},
|
||||
Stream: true,
|
||||
}
|
||||
|
||||
errStream := svc.Chat(recStream, nil, reqStream)
|
||||
if errStream != nil {
|
||||
t.Fatalf("unexpected error in respond streaming: %v", errStream)
|
||||
}
|
||||
|
||||
scanner := bufio.NewScanner(recStream.Body)
|
||||
var receivedContent strings.Builder
|
||||
var receivedReasoning strings.Builder
|
||||
var sawDone bool
|
||||
|
||||
for scanner.Scan() {
|
||||
line := scanner.Text()
|
||||
if strings.HasPrefix(line, "data: ") {
|
||||
payload := strings.TrimPrefix(line, "data: ")
|
||||
if payload == "[DONE]" {
|
||||
sawDone = true
|
||||
continue
|
||||
}
|
||||
var sResp StreamResponse
|
||||
if err := json.Unmarshal([]byte(payload), &sResp); err == nil && len(sResp.Choices) > 0 {
|
||||
delta := sResp.Choices[0].Delta
|
||||
if delta.ReasoningContent != "" {
|
||||
receivedReasoning.WriteString(delta.ReasoningContent)
|
||||
}
|
||||
if delta.Content != "" {
|
||||
receivedContent.WriteString(delta.Content)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if !sawDone {
|
||||
t.Fatalf("expected [DONE] in stream")
|
||||
}
|
||||
if receivedReasoning.String() != "Analyzing the problem." {
|
||||
t.Fatalf("unexpected streamed reasoning: %q", receivedReasoning.String())
|
||||
}
|
||||
if receivedContent.String() != "The solution is 42." {
|
||||
t.Fatalf("unexpected streamed content: %q", receivedContent.String())
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user