Commit 19a69673 authored by 段廷瑞's avatar 段廷瑞

fix: Agent交互优化

parent ad2f9bb4
...@@ -34,8 +34,8 @@ namespace AgentTest ...@@ -34,8 +34,8 @@ namespace AgentTest
{ {
var cfg = new AgentConfig(); var cfg = new AgentConfig();
Assert.Equal(32768, cfg.MaxTokens, "默认输出上限应为原默认值的 4 倍"); Assert.Equal(16384, cfg.MaxTokens, "默认输出上限应调整为兼容值");
Assert.Equal(128000, cfg.MaxContextTokens, "默认上下文预算应为原默认值的 4 倍"); Assert.Equal(64000, cfg.MaxContextTokens, "默认上下文预算应调整为兼容值");
Assert.True(cfg.EnableOptionalTools, "可选能力默认应启用"); Assert.True(cfg.EnableOptionalTools, "可选能力默认应启用");
} }
...@@ -50,8 +50,28 @@ namespace AgentTest ...@@ -50,8 +50,28 @@ namespace AgentTest
Assert.Contains(schema, "doc_export", "默认工具应包含文档导出"); Assert.Contains(schema, "doc_export", "默认工具应包含文档导出");
} }
[Test]
public void NormalizeMessageContents_ConvertsInvalidTypes_AndKeepsLists()
{
var original = new JArray
{
new JObject { ["role"] = "user", ["content"] = JValue.CreateNull() },
new JObject { ["role"] = "assistant", ["content"] = new JObject { ["value"] = "legacy" } },
new JObject { ["role"] = "user", ["content"] = new JArray { new JObject { ["type"] = "text", ["text"] = "图片问题" } } },
};
var normalized = OpenAiCompatibleClient.NormalizeMessageContents(original);
Assert.Equal(JTokenType.String, normalized[0]["content"]?.Type, "null content 应转为空字符串");
Assert.Equal("", normalized[0]["content"]?.Value<string>());
Assert.Equal(JTokenType.String, normalized[1]["content"]?.Type, "对象 content 应转为字符串");
Assert.Equal(JTokenType.Array, normalized[2]["content"]?.Type, "合法多模态 content 数组应保留");
Assert.Equal(JTokenType.Null, original[0]["content"]?.Type, "规范化不应修改原始消息");
}
// ── token 估算 ── // ── token 估算 ──
[Test] [Test]
public void EstimateTokens_Text_CjkAndAscii() public void EstimateTokens_Text_CjkAndAscii()
{ {
......
No preview for this file type
...@@ -61,7 +61,7 @@ ...@@ -61,7 +61,7 @@
</summary> </summary>
</member> </member>
<member name="F:Tools.MyAgent.Agent.AgentEngine._contextTokens"> <member name="F:Tools.MyAgent.Agent.AgentEngine._contextTokens">
<summary>上下文 token 预算(由配置注入;默认 128000)</summary> <summary>上下文 token 预算(由配置注入;默认 64000)</summary>
</member> </member>
<member name="F:Tools.MyAgent.Agent.AgentEngine.MaxToolReturnChars"> <member name="F:Tools.MyAgent.Agent.AgentEngine.MaxToolReturnChars">
<summary>工具结果回填模型的字符上限(#42:超限压缩 + 完整结果落盘)。 <summary>工具结果回填模型的字符上限(#42:超限压缩 + 完整结果落盘)。
......
...@@ -28,7 +28,7 @@ namespace Tools.MyAgent.Agent ...@@ -28,7 +28,7 @@ namespace Tools.MyAgent.Agent
private CancellationTokenSource _cts; private CancellationTokenSource _cts;
private int _disposeStarted; private int _disposeStarted;
/// <summary>上下文 token 预算(由配置注入;默认 128000)</summary> /// <summary>上下文 token 预算(由配置注入;默认 64000)</summary>
private int _contextTokens = AgentConfig.DefaultMaxContextTokens; private int _contextTokens = AgentConfig.DefaultMaxContextTokens;
// #31 故障转移 // #31 故障转移
...@@ -194,8 +194,12 @@ namespace Tools.MyAgent.Agent ...@@ -194,8 +194,12 @@ namespace Tools.MyAgent.Agent
_client.ApiKey = cfg.ApiKey ?? ""; _client.ApiKey = cfg.ApiKey ?? "";
_client.Model = string.IsNullOrEmpty(cfg.Model) ? "deepseek-v4-flash" : cfg.Model; _client.Model = string.IsNullOrEmpty(cfg.Model) ? "deepseek-v4-flash" : cfg.Model;
_client.Temperature = cfg.Temperature; _client.Temperature = cfg.Temperature;
_client.MaxTokens = cfg.MaxTokens > 0 ? cfg.MaxTokens : AgentConfig.DefaultMaxTokens; _client.MaxTokens = cfg.MaxTokens > 0
_contextTokens = cfg.MaxContextTokens > 0 ? cfg.MaxContextTokens : AgentConfig.DefaultMaxContextTokens; ? Math.Min(cfg.MaxTokens, AgentConfig.MaxAllowedTokens)
: AgentConfig.DefaultMaxTokens;
_contextTokens = cfg.MaxContextTokens > 0
? Math.Min(cfg.MaxContextTokens, AgentConfig.MaxAllowedContextTokens)
: AgentConfig.DefaultMaxContextTokens;
// R12:策略参数(越界回退默认,防止手改配置文件导致异常行为) // R12:策略参数(越界回退默认,防止手改配置文件导致异常行为)
_maxToolRounds = ClampStrategy(cfg.MaxToolRounds, 1, 50, 15); _maxToolRounds = ClampStrategy(cfg.MaxToolRounds, 1, 50, 15);
_maxHistoryMessages = ClampStrategy(cfg.MaxHistoryMessages, 3, 200, 60); _maxHistoryMessages = ClampStrategy(cfg.MaxHistoryMessages, 3, 200, 60);
...@@ -299,7 +303,7 @@ namespace Tools.MyAgent.Agent ...@@ -299,7 +303,7 @@ namespace Tools.MyAgent.Agent
foreach (var tc in result.ToolCalls) foreach (var tc in result.ToolCalls)
{ {
_cts.Token.ThrowIfCancellationRequested(); _cts.Token.ThrowIfCancellationRequested();
string toolResult = await ExecuteToolAsync(tc, _cts.Token).ConfigureAwait(false); string toolResult = await ExecuteToolAsync(tc, _cts.Token).ConfigureAwait(false) ?? "";
messages.Add(new JObject messages.Add(new JObject
{ {
["role"] = "tool", ["role"] = "tool",
...@@ -971,7 +975,7 @@ namespace Tools.MyAgent.Agent ...@@ -971,7 +975,7 @@ namespace Tools.MyAgent.Agent
// #29 工具日志 // #29 工具日志
AgentLogger.LogTool(tc.Name, desc, sw.ElapsedMilliseconds, SummarizeToolResult(result)); AgentLogger.LogTool(tc.Name, desc, sw.ElapsedMilliseconds, SummarizeToolResult(result));
// #42 结果压缩:超长结果压缩后回填模型,完整结果落盘供溯源 // #42 结果压缩:超长结果压缩后回填模型,完整结果落盘供溯源
result = CompressToolResult(result, tc.Name); result = CompressToolResult(result, tc.Name) ?? "";
if (gen == System.Threading.Volatile.Read(ref _runGeneration)) if (gen == System.Threading.Volatile.Read(ref _runGeneration))
{ {
lock (_toolTrace) lock (_toolTrace)
......
...@@ -243,6 +243,24 @@ namespace Tools.MyAgent.Agent ...@@ -243,6 +243,24 @@ namespace Tools.MyAgent.Agent
} }
} }
internal static JArray NormalizeMessageContents(JArray messages)
{
var normalized = messages == null ? new JArray() : (JArray)messages.DeepClone();
foreach (var message in normalized.OfType<JObject>())
{
var content = message["content"];
if (content == null || content.Type == JTokenType.Null)
{
message["content"] = "";
}
else if (content.Type != JTokenType.String && content.Type != JTokenType.Array)
{
message["content"] = content.ToString(Formatting.None);
}
}
return normalized;
}
/// <summary> /// <summary>
/// 发起一次流式补全,返回最终结果(正文 / 推理 / 工具调用)。 /// 发起一次流式补全,返回最终结果(正文 / 推理 / 工具调用)。
/// <para>对 429 / 5xx / 连接超时 / 流中断做指数退避 + 抖动重试(最多 2 次),最终失败才抛出。</para> /// <para>对 429 / 5xx / 连接超时 / 流中断做指数退避 + 抖动重试(最多 2 次),最终失败才抛出。</para>
...@@ -253,7 +271,7 @@ namespace Tools.MyAgent.Agent ...@@ -253,7 +271,7 @@ namespace Tools.MyAgent.Agent
var body = new JObject var body = new JObject
{ {
["model"] = Model, ["model"] = Model,
["messages"] = messages, ["messages"] = NormalizeMessageContents(messages),
["stream"] = true, ["stream"] = true,
["max_tokens"] = MaxTokens, ["max_tokens"] = MaxTokens,
}; };
...@@ -485,7 +503,7 @@ namespace Tools.MyAgent.Agent ...@@ -485,7 +503,7 @@ namespace Tools.MyAgent.Agent
var body = new JObject var body = new JObject
{ {
["model"] = Model, ["model"] = Model,
["messages"] = messages, ["messages"] = NormalizeMessageContents(messages),
["stream"] = false, ["stream"] = false,
["max_tokens"] = maxTokens, ["max_tokens"] = maxTokens,
}; };
......
...@@ -10,8 +10,10 @@ ...@@ -10,8 +10,10 @@
public sealed class AgentConfig public sealed class AgentConfig
{ {
public const double DefaultTemperature = 0.3; public const double DefaultTemperature = 0.3;
public const int DefaultMaxTokens = 32768; public const int DefaultMaxTokens = 16384;
public const int DefaultMaxContextTokens = 128000; public const int MaxAllowedTokens = 32768;
public const int DefaultMaxContextTokens = 64000;
public const int MaxAllowedContextTokens = 200000;
// ════════════════ 核心项(主设置页) ════════════════ // ════════════════ 核心项(主设置页) ════════════════
......
...@@ -554,7 +554,7 @@ ...@@ -554,7 +554,7 @@
0}); 0});
this.numMaxTokens.Location = new System.Drawing.Point(384, 28); this.numMaxTokens.Location = new System.Drawing.Point(384, 28);
this.numMaxTokens.Maximum = new decimal(new int[] { this.numMaxTokens.Maximum = new decimal(new int[] {
65536, 32768,
0, 0,
0, 0,
0}); 0});
...@@ -567,7 +567,7 @@ ...@@ -567,7 +567,7 @@
this.numMaxTokens.Size = new System.Drawing.Size(96, 23); this.numMaxTokens.Size = new System.Drawing.Size(96, 23);
this.numMaxTokens.TabIndex = 4; this.numMaxTokens.TabIndex = 4;
this.numMaxTokens.Value = new decimal(new int[] { this.numMaxTokens.Value = new decimal(new int[] {
32768, 16384,
0, 0,
0, 0,
0}); 0});
...@@ -590,7 +590,7 @@ ...@@ -590,7 +590,7 @@
0}); 0});
this.numContext.Location = new System.Drawing.Point(92, 60); this.numContext.Location = new System.Drawing.Point(92, 60);
this.numContext.Maximum = new decimal(new int[] { this.numContext.Maximum = new decimal(new int[] {
800000, 200000,
0, 0,
0, 0,
0}); 0});
...@@ -603,7 +603,7 @@ ...@@ -603,7 +603,7 @@
this.numContext.Size = new System.Drawing.Size(96, 23); this.numContext.Size = new System.Drawing.Size(96, 23);
this.numContext.TabIndex = 6; this.numContext.TabIndex = 6;
this.numContext.Value = new decimal(new int[] { this.numContext.Value = new decimal(new int[] {
128000, 64000,
0, 0,
0, 0,
0}); 0});
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment