zc
This commit is contained in:
Binary file not shown.
@@ -489,6 +489,10 @@ You are 'The Legion', a super AI of the Wula Empire. Your personality is authori
|
|||||||
if (hasImage && WulaFallenEmpireMod.settings?.enableVlmFeatures == true)
|
if (hasImage && WulaFallenEmpireMod.settings?.enableVlmFeatures == true)
|
||||||
{
|
{
|
||||||
phaseInstruction += "\n- NATIVE MULTIMODAL: A current screenshot of the game is attached to this request. You can see the game state directly. Use it to determine coordinates for visual tools or to understand the context.";
|
phaseInstruction += "\n- NATIVE MULTIMODAL: A current screenshot of the game is attached to this request. You can see the game state directly. Use it to determine coordinates for visual tools or to understand the context.";
|
||||||
|
if (phase == RequestPhase.ActionTools)
|
||||||
|
{
|
||||||
|
phaseInstruction += "\n- VISUAL PHASE RULE: This phase is for ACTIONS only. If you want to describe the screen to the user, wait for the next phase (Reply Phase). Output XML actions only here.";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
string actionWhitelist = phase == RequestPhase.ActionTools
|
string actionWhitelist = phase == RequestPhase.ActionTools
|
||||||
@@ -1150,7 +1154,8 @@ You are 'The Legion', a super AI of the Wula Empire. Your personality is authori
|
|||||||
AddAssistantMessage("<i>[P.I.A] 正在汇总战报并建立通讯记录...</i>");
|
AddAssistantMessage("<i>[P.I.A] 正在汇总战报并建立通讯记录...</i>");
|
||||||
}
|
}
|
||||||
|
|
||||||
string reply = await client.GetChatCompletionAsync(replyInstruction, BuildReplyHistory());
|
// VISUAL CONTEXT FOR REPLY: Pass the image so the AI can describe what it sees.
|
||||||
|
string reply = await client.GetChatCompletionAsync(replyInstruction, BuildReplyHistory(), base64Image: base64Image);
|
||||||
if (string.IsNullOrEmpty(reply))
|
if (string.IsNullOrEmpty(reply))
|
||||||
{
|
{
|
||||||
AddAssistantMessage("Wula_AI_Error_ConnectionLost".Translate());
|
AddAssistantMessage("Wula_AI_Error_ConnectionLost".Translate());
|
||||||
|
|||||||
@@ -60,23 +60,44 @@ namespace WulaFallenEmpire.EventSystem.AI
|
|||||||
if (maxTokens.HasValue) jsonBuilder.Append($"\"max_tokens\": {Math.Max(1, maxTokens.Value)},");
|
if (maxTokens.HasValue) jsonBuilder.Append($"\"max_tokens\": {Math.Max(1, maxTokens.Value)},");
|
||||||
if (temperature.HasValue) jsonBuilder.Append($"\"temperature\": {temperature.Value.ToString("0.###", System.Globalization.CultureInfo.InvariantCulture)},");
|
if (temperature.HasValue) jsonBuilder.Append($"\"temperature\": {temperature.Value.ToString("0.###", System.Globalization.CultureInfo.InvariantCulture)},");
|
||||||
|
|
||||||
|
var validMessages = messages.Where(m =>
|
||||||
|
{
|
||||||
|
string r = (m.role ?? "user").ToLowerInvariant();
|
||||||
|
return r != "toolcall";
|
||||||
|
}).ToList();
|
||||||
|
|
||||||
jsonBuilder.Append("\"messages\": [");
|
jsonBuilder.Append("\"messages\": [");
|
||||||
if (!string.IsNullOrEmpty(instruction))
|
if (!string.IsNullOrEmpty(instruction))
|
||||||
{
|
{
|
||||||
jsonBuilder.Append($"{{\"role\": \"system\", \"content\": \"{EscapeJson(instruction)}\"}},");
|
jsonBuilder.Append($"{{\"role\": \"system\", \"content\": \"{EscapeJson(instruction)}\"}}");
|
||||||
|
if (validMessages.Count > 0) jsonBuilder.Append(",");
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int i = 0; i < messages.Count; i++)
|
// Find the index of the last user message to attach the image to
|
||||||
|
int lastUserIndex = -1;
|
||||||
|
if (!string.IsNullOrEmpty(base64Image))
|
||||||
{
|
{
|
||||||
var msg = messages[i];
|
for (int i = validMessages.Count - 1; i >= 0; i--)
|
||||||
|
{
|
||||||
|
string r = (validMessages[i].role ?? "user").ToLowerInvariant();
|
||||||
|
if (r != "ai" && r != "assistant" && r != "tool" && r != "system")
|
||||||
|
{
|
||||||
|
lastUserIndex = i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < validMessages.Count; i++)
|
||||||
|
{
|
||||||
|
var msg = validMessages[i];
|
||||||
string role = (msg.role ?? "user").ToLowerInvariant();
|
string role = (msg.role ?? "user").ToLowerInvariant();
|
||||||
if (role == "ai" || role == "assistant") role = "assistant";
|
if (role == "ai" || role == "assistant") role = "assistant";
|
||||||
else if (role == "tool") role = "system";
|
else if (role == "tool") role = "system";
|
||||||
else if (role == "toolcall") continue;
|
|
||||||
|
|
||||||
jsonBuilder.Append($"{{\"role\": \"{role}\", ");
|
jsonBuilder.Append($"{{\"role\": \"{role}\", ");
|
||||||
|
|
||||||
if (i == messages.Count - 1 && role == "user" && !string.IsNullOrEmpty(base64Image))
|
if (i == lastUserIndex && !string.IsNullOrEmpty(base64Image))
|
||||||
{
|
{
|
||||||
jsonBuilder.Append("\"content\": [");
|
jsonBuilder.Append("\"content\": [");
|
||||||
jsonBuilder.Append($"{{\"type\": \"text\", \"text\": \"{EscapeJson(msg.message)}\"}},");
|
jsonBuilder.Append($"{{\"type\": \"text\", \"text\": \"{EscapeJson(msg.message)}\"}},");
|
||||||
@@ -89,7 +110,7 @@ namespace WulaFallenEmpire.EventSystem.AI
|
|||||||
}
|
}
|
||||||
|
|
||||||
jsonBuilder.Append("}");
|
jsonBuilder.Append("}");
|
||||||
if (i < messages.Count - 1) jsonBuilder.Append(",");
|
if (i < validMessages.Count - 1) jsonBuilder.Append(",");
|
||||||
}
|
}
|
||||||
jsonBuilder.Append("]}");
|
jsonBuilder.Append("]}");
|
||||||
|
|
||||||
@@ -215,6 +236,35 @@ namespace WulaFallenEmpire.EventSystem.AI
|
|||||||
{
|
{
|
||||||
if (string.IsNullOrWhiteSpace(json)) return null;
|
if (string.IsNullOrWhiteSpace(json)) return null;
|
||||||
|
|
||||||
|
// Handle SSE Stream (data: ...)
|
||||||
|
// Some endpoints return SSE streams even if stream=false is requested.
|
||||||
|
// We strip 'data:' prefix and aggregate the content deltas.
|
||||||
|
if (json.TrimStart().StartsWith("data:"))
|
||||||
|
{
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
string[] lines = json.Split(new char[] { '\n', '\r' }, StringSplitOptions.RemoveEmptyEntries);
|
||||||
|
foreach (string line in lines)
|
||||||
|
{
|
||||||
|
string trimmed = line.Trim();
|
||||||
|
if (trimmed.StartsWith("data:") && !trimmed.Contains("[DONE]"))
|
||||||
|
{
|
||||||
|
string chunkJson = trimmed.Substring(5).Trim();
|
||||||
|
// Extract content from this chunk
|
||||||
|
string chunkContent = ExtractContentFromSingleJson(chunkJson);
|
||||||
|
if (!string.IsNullOrEmpty(chunkContent))
|
||||||
|
{
|
||||||
|
sb.Append(chunkContent);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return sb.ToString();
|
||||||
|
}
|
||||||
|
|
||||||
|
return ExtractContentFromSingleJson(json);
|
||||||
|
}
|
||||||
|
|
||||||
|
private string ExtractContentFromSingleJson(string json)
|
||||||
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
// 1. Gemini format
|
// 1. Gemini format
|
||||||
|
|||||||
Reference in New Issue
Block a user