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

fix: Agent交互优化

parent ad2f9bb4
......@@ -34,8 +34,8 @@ namespace AgentTest
{
var cfg = new AgentConfig();
Assert.Equal(32768, cfg.MaxTokens, "默认输出上限应为原默认值的 4 倍");
Assert.Equal(128000, cfg.MaxContextTokens, "默认上下文预算应为原默认值的 4 倍");
Assert.Equal(16384, cfg.MaxTokens, "默认输出上限应调整为兼容值");
Assert.Equal(64000, cfg.MaxContextTokens, "默认上下文预算应调整为兼容值");
Assert.True(cfg.EnableOptionalTools, "可选能力默认应启用");
}
......@@ -50,8 +50,28 @@ namespace AgentTest
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 估算 ──
[Test]
public void EstimateTokens_Text_CjkAndAscii()
{
......
No preview for this file type
......@@ -61,7 +61,7 @@
</summary>
</member>
<member name="F:Tools.MyAgent.Agent.AgentEngine._contextTokens">
<summary>上下文 token 预算(由配置注入;默认 128000)</summary>
<summary>上下文 token 预算(由配置注入;默认 64000)</summary>
</member>
<member name="F:Tools.MyAgent.Agent.AgentEngine.MaxToolReturnChars">
<summary>工具结果回填模型的字符上限(#42:超限压缩 + 完整结果落盘)。
......
......@@ -28,7 +28,7 @@ namespace Tools.MyAgent.Agent
private CancellationTokenSource _cts;
private int _disposeStarted;
/// <summary>上下文 token 预算(由配置注入;默认 128000)</summary>
/// <summary>上下文 token 预算(由配置注入;默认 64000)</summary>
private int _contextTokens = AgentConfig.DefaultMaxContextTokens;
// #31 故障转移
......@@ -194,8 +194,12 @@ namespace Tools.MyAgent.Agent
_client.ApiKey = cfg.ApiKey ?? "";
_client.Model = string.IsNullOrEmpty(cfg.Model) ? "deepseek-v4-flash" : cfg.Model;
_client.Temperature = cfg.Temperature;
_client.MaxTokens = cfg.MaxTokens > 0 ? cfg.MaxTokens : AgentConfig.DefaultMaxTokens;
_contextTokens = cfg.MaxContextTokens > 0 ? cfg.MaxContextTokens : AgentConfig.DefaultMaxContextTokens;
_client.MaxTokens = cfg.MaxTokens > 0
? Math.Min(cfg.MaxTokens, AgentConfig.MaxAllowedTokens)
: AgentConfig.DefaultMaxTokens;
_contextTokens = cfg.MaxContextTokens > 0
? Math.Min(cfg.MaxContextTokens, AgentConfig.MaxAllowedContextTokens)
: AgentConfig.DefaultMaxContextTokens;
// R12:策略参数(越界回退默认,防止手改配置文件导致异常行为)
_maxToolRounds = ClampStrategy(cfg.MaxToolRounds, 1, 50, 15);
_maxHistoryMessages = ClampStrategy(cfg.MaxHistoryMessages, 3, 200, 60);
......@@ -299,7 +303,7 @@ namespace Tools.MyAgent.Agent
foreach (var tc in result.ToolCalls)
{
_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
{
["role"] = "tool",
......@@ -971,7 +975,7 @@ namespace Tools.MyAgent.Agent
// #29 工具日志
AgentLogger.LogTool(tc.Name, desc, sw.ElapsedMilliseconds, SummarizeToolResult(result));
// #42 结果压缩:超长结果压缩后回填模型,完整结果落盘供溯源
result = CompressToolResult(result, tc.Name);
result = CompressToolResult(result, tc.Name) ?? "";
if (gen == System.Threading.Volatile.Read(ref _runGeneration))
{
lock (_toolTrace)
......
......@@ -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>
/// 发起一次流式补全,返回最终结果(正文 / 推理 / 工具调用)。
/// <para>对 429 / 5xx / 连接超时 / 流中断做指数退避 + 抖动重试(最多 2 次),最终失败才抛出。</para>
......@@ -253,7 +271,7 @@ namespace Tools.MyAgent.Agent
var body = new JObject
{
["model"] = Model,
["messages"] = messages,
["messages"] = NormalizeMessageContents(messages),
["stream"] = true,
["max_tokens"] = MaxTokens,
};
......@@ -485,7 +503,7 @@ namespace Tools.MyAgent.Agent
var body = new JObject
{
["model"] = Model,
["messages"] = messages,
["messages"] = NormalizeMessageContents(messages),
["stream"] = false,
["max_tokens"] = maxTokens,
};
......
......@@ -10,8 +10,10 @@
public sealed class AgentConfig
{
public const double DefaultTemperature = 0.3;
public const int DefaultMaxTokens = 32768;
public const int DefaultMaxContextTokens = 128000;
public const int DefaultMaxTokens = 16384;
public const int MaxAllowedTokens = 32768;
public const int DefaultMaxContextTokens = 64000;
public const int MaxAllowedContextTokens = 200000;
// ════════════════ 核心项(主设置页) ════════════════
......
......@@ -554,7 +554,7 @@
0});
this.numMaxTokens.Location = new System.Drawing.Point(384, 28);
this.numMaxTokens.Maximum = new decimal(new int[] {
65536,
32768,
0,
0,
0});
......@@ -567,7 +567,7 @@
this.numMaxTokens.Size = new System.Drawing.Size(96, 23);
this.numMaxTokens.TabIndex = 4;
this.numMaxTokens.Value = new decimal(new int[] {
32768,
16384,
0,
0,
0});
......@@ -590,7 +590,7 @@
0});
this.numContext.Location = new System.Drawing.Point(92, 60);
this.numContext.Maximum = new decimal(new int[] {
800000,
200000,
0,
0,
0});
......@@ -603,7 +603,7 @@
this.numContext.Size = new System.Drawing.Size(96, 23);
this.numContext.TabIndex = 6;
this.numContext.Value = new decimal(new int[] {
128000,
64000,
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