fix(openai): Auto-Context, Tool-Result-Matching, Payload-Preview, leere Bubbles
- Auto-Context (Embedding-Suche) für OpenAI-Provider aktiviert: BuildAutoContextAsync auf internal static refactored und in StreamChat + ChatNonStreaming integriert - Tool-Results mit Role="tool" (OpenAI-Konvention) werden in BuildHistoryFromDb jetzt korrekt erkannt (vorher nur Role="user"/Anthropic) - Payload-Preview zeigt für OpenAI-Provider echtes API-Format (function-Wrapper, tool_choice:"auto", max_tokens, stream_options, extra_body) - Tool-Input (Argumente) wird im SSE tool_end-Event mitgesendet (fehlte im OpenAI-Pfad) - Leere Bubbles durch Whitespace-only Text nach </think>-Extraktion behoben (Trim in DB-Save, BuildHistoryFromDb und Frontend-Guard) - History-Toggle-Bug: var→const in for-Loop (Block-Scoping für Closures), tool_result-Matching per data-tool-call-id statt blindes letztes Element - Non-Streaming max_tokens für MiniMax auf 32768 + extra_body.reasoning_split Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
1 parent
ecddbe5f36
commit
1fe04025d3
9 files changed
+164
-42
No files matched your search
@@ -317,8 +317,54 @@ public static class SessionEndpoint
|
||||
var toolChoice = hasTools || !string.IsNullOrEmpty(agent.WebSearchVersion) ? "any" : null;
|
||||
var effectiveChoice = toolChoice == "any" ? "any" : "auto";
|
||||
|
||||
// Payload zusammenbauen (Anthropic-Format)
|
||||
var payload = new Dictionary<string, object>
|
||||
// OpenAI-kompatible Provider: Payload im tatsächlichen API-Format anzeigen
|
||||
if (previewProvider)
|
||||
{
|
||||
var (provider, _) = OpenAiService.ParseModelString(modelId);
|
||||
var maxTokens = provider == "minimax" ? 32768 : 16384;
|
||||
|
||||
// Messages konvertieren (Anthropic → OpenAI-Format)
|
||||
var openAiMessages = OpenAiService.BuildApiMessages(systemPromptText, messages);
|
||||
|
||||
// Tools konvertieren (input_schema → function/parameters)
|
||||
var openAiTools = tools.Count > 0
|
||||
? OpenAiService.ConvertTo_openAiToolDefs(tools.ToArray())
|
||||
: new List<object>();
|
||||
|
||||
var payload = new Dictionary<string, object>
|
||||
{
|
||||
["model"] = modelId,
|
||||
["max_tokens"] = maxTokens,
|
||||
["messages"] = openAiMessages,
|
||||
["stream"] = true,
|
||||
["stream_options"] = new { include_usage = true }
|
||||
};
|
||||
|
||||
if (openAiTools.Count > 0)
|
||||
{
|
||||
payload["tools"] = openAiTools;
|
||||
payload["tool_choice"] = "auto";
|
||||
}
|
||||
|
||||
if (provider == "minimax")
|
||||
payload["extra_body"] = new { reasoning_split = true };
|
||||
|
||||
if (provider == "nvidia")
|
||||
{
|
||||
var nvidiaModelId = modelId.Contains(":") ? modelId.Split(':')[1] : modelId;
|
||||
if (nvidiaModelId.Contains("kimi-k2", StringComparison.OrdinalIgnoreCase)
|
||||
|| nvidiaModelId.Contains("qwq", StringComparison.OrdinalIgnoreCase)
|
||||
|| nvidiaModelId.Contains("deepseek-r1", StringComparison.OrdinalIgnoreCase))
|
||||
payload["chat_template_kwargs"] = new { thinking = true };
|
||||
}
|
||||
|
||||
ctx.Response.ContentType = "application/json; charset=utf-8";
|
||||
await ctx.Response.WriteAsync(JsonSerializer.Serialize(payload, new JsonSerializerOptions { WriteIndented = true }));
|
||||
return;
|
||||
}
|
||||
|
||||
// Anthropic-Format Payload
|
||||
var anthropicPayload = new Dictionary<string, object>
|
||||
{
|
||||
["model"] = modelId,
|
||||
["max_tokens"] = 16384,
|
||||
@@ -327,16 +373,16 @@ public static class SessionEndpoint
|
||||
};
|
||||
|
||||
if (systemPrompt.Count > 0)
|
||||
payload["system"] = systemPrompt;
|
||||
anthropicPayload["system"] = systemPrompt;
|
||||
|
||||
if (tools.Count > 0)
|
||||
{
|
||||
payload["tools"] = tools;
|
||||
payload["tool_choice"] = new { type = effectiveChoice };
|
||||
anthropicPayload["tools"] = tools;
|
||||
anthropicPayload["tool_choice"] = new { type = effectiveChoice };
|
||||
}
|
||||
|
||||
ctx.Response.ContentType = "application/json; charset=utf-8";
|
||||
await ctx.Response.WriteAsync(JsonSerializer.Serialize(payload, new JsonSerializerOptions { WriteIndented = true }));
|
||||
await ctx.Response.WriteAsync(JsonSerializer.Serialize(anthropicPayload, new JsonSerializerOptions { WriteIndented = true }));
|
||||
}
|
||||
|
||||
private static async Task HandleStreaming(HttpContext ctx, DatabaseService db, StreamingTracker streamingTracker)
|
||||
|
||||
Reference in new issue
Block a user