Commit c64815c5 authored by 段廷瑞's avatar 段廷瑞

feat: 智能体功能完善

parent 79a55a4c
...@@ -65,3 +65,4 @@ bin ...@@ -65,3 +65,4 @@ bin
*.zip *.zip
/AppHome/AgentChat /AppHome/AgentChat
/AppHome/Agent/history /AppHome/Agent/history
/AppHome/Agent
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
This diff is collapsed.
This diff is collapsed.
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<configuration> <configuration>
<appSettings> <appSettings>
<add key="UpdateTime" value="2021-12-30 10:52:06.703" /> <add key="UpdateTime" value="2021-12-30 10:52:06.703" />
...@@ -25,5 +25,71 @@ ...@@ -25,5 +25,71 @@
<bindingRedirect oldVersion="0.0.0.0-12.0.0.0" newVersion="12.0.0.0" /> <bindingRedirect oldVersion="0.0.0.0-12.0.0.0" newVersion="12.0.0.0" />
</dependentAssembly> </dependentAssembly>
</assemblyBinding> </assemblyBinding>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="BouncyCastle.Crypto" publicKeyToken="0e99375e54769942" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-1.8.6.0" newVersion="1.8.6.0" />
</dependentAssembly>
</assemblyBinding>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="System.Memory" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.0.2.0" newVersion="4.0.2.0" />
</dependentAssembly>
</assemblyBinding>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="System.Buffers" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.0.4.0" newVersion="4.0.4.0" />
</dependentAssembly>
</assemblyBinding>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="System.Numerics.Vectors" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.1.5.0" newVersion="4.1.5.0" />
</dependentAssembly>
</assemblyBinding>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="System.Runtime.CompilerServices.Unsafe" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-6.0.1.0" newVersion="6.0.1.0" />
</dependentAssembly>
</assemblyBinding>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="Microsoft.Bcl.AsyncInterfaces" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-8.0.0.0" newVersion="8.0.0.0" />
</dependentAssembly>
</assemblyBinding>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="System.Text.Json" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-8.0.0.0" newVersion="8.0.0.0" />
</dependentAssembly>
</assemblyBinding>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="System.Threading.Channels" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-7.0.0.0" newVersion="7.0.0.0" />
</dependentAssembly>
</assemblyBinding>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="System.Threading.Tasks.Extensions" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.5.4.0" newVersion="4.5.4.0" />
</dependentAssembly>
</assemblyBinding>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="System.ValueTuple" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.5.0.0" newVersion="4.5.0.0" />
</dependentAssembly>
</assemblyBinding>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="Microsoft.Bcl.HashCode" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-6.0.0.0" newVersion="6.0.0.0" />
</dependentAssembly>
</assemblyBinding>
</runtime> </runtime>
</configuration> </configuration>
\ No newline at end of file
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
using System;
using System.Threading;
using System.Threading.Tasks;
using Newtonsoft.Json.Linq;
namespace Tools.MyAgent.Agent
{
/// <summary>
/// 故障转移策略:主模型连续失败时自动切换到备用模型。
/// <para>从 AgentEngine 解耦,独立测试、独立配置。</para>
/// </summary>
public sealed class FailoverPolicy
{
private IOpenAiChatClient _primary;
private IOpenAiChatClient _backup;
private IOpenAiChatClient _current;
private int _consecutiveFailures;
private bool _failedOver;
public bool Enabled { get; private set; }
public bool IsActive => _failedOver;
public FailoverPolicy(IOpenAiChatClient primary, IOpenAiChatClient backup)
{
_primary = primary;
_backup = backup;
_current = primary;
}
public void Configure(bool enabled, string backupBaseUrl, string backupModel, string backupApiKey)
{
Enabled = enabled;
if (_backup != null)
{
_backup.BaseUrl = string.IsNullOrEmpty(backupBaseUrl) ? "http://localhost:11434/v1" : backupBaseUrl;
_backup.ApiKey = backupApiKey ?? "";
_backup.Model = string.IsNullOrEmpty(backupModel) ? "qwen2.5" : backupModel;
_backup.Temperature = 0.3;
_backup.MaxTokens = 8192;
}
if (!enabled && _failedOver)
{
RestorePrimary();
}
_consecutiveFailures = 0;
}
public IOpenAiChatClient CurrentClient => _current;
/// <summary>主客户端被外部重建(如代理开关变化)时同步替换引用,避免策略持有已释放的旧客户端</summary>
public void SetPrimary(IOpenAiChatClient primary)
{
if (primary == null) return;
_primary = primary;
if (!_failedOver) _current = primary; // 未处于备用状态时立即跟随新主客户端
}
/// <summary>记录一次成功调用</summary>
public void RecordSuccess()
{
_consecutiveFailures = 0;
if (_failedOver)
{
RestorePrimary();
_failedOver = false;
}
}
/// <summary>记录一次失败;若启用且连续失败达阈值,返回 true 表示已切换</summary>
public bool RecordFailure(Exception ex)
{
if (!IsServiceError(ex))
{
_consecutiveFailures = 0;
return false;
}
_consecutiveFailures++;
if (Enabled && _consecutiveFailures >= 2 && !_failedOver)
{
SwitchToBackup();
_failedOver = true;
_consecutiveFailures = 0;
return true;
}
return false;
}
private void SwitchToBackup()
{
try { _backup.UseSystemProxy = true; } catch { }
_current = _backup;
}
private void RestorePrimary()
{
_current = _primary;
}
private static bool IsServiceError(Exception ex)
{
var msg = ex?.InnerException?.Message ?? ex?.Message ?? "";
return msg.Contains("429") || msg.Contains("500") || msg.Contains("502") || msg.Contains("503")
|| msg.Contains("504") || msg.Contains("超时") || msg.Contains("timeout") || msg.Contains("timed out")
|| ex is System.Net.Http.HttpRequestException
|| msg.Contains("connection") || msg.Contains("连接");
}
}
}
\ No newline at end of file
using Newtonsoft.Json.Linq;
using System.Threading;
using System.Threading.Tasks;
namespace Tools.MyAgent.Agent
{
/// <summary>
/// OpenAI 兼容聊天补全客户端接口,支持 SSE 流式 + function calling。
/// <para>换厂商只改 BaseUrl / Model / ApiKey。</para>
/// </summary>
public interface IOpenAiChatClient
{
string BaseUrl { get; set; }
string ApiKey { get; set; }
string Model { get; set; }
double Temperature { get; set; }
int MaxTokens { get; set; }
bool UseSystemProxy { get; set; }
/// <summary>发起一次流式补全,返回最终结果</summary>
Task<ChatResult> SendAsync(JArray messages, JArray tools, bool enableTools, CancellationToken ct);
/// <summary>非流式补全,一次性返回正文</summary>
Task<string> CompleteAsync(JArray messages, int maxTokens, CancellationToken ct);
/// <summary>连接测试</summary>
Task<(bool Ok, string Message)> TestConnectionAsync(CancellationToken ct);
/// <summary>取消当前请求</summary>
void Cancel();
/// <summary>释放底层资源</summary>
void Dispose();
}
}
\ No newline at end of file
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
using System;
namespace Tools.MyAgent
{
/// <summary>
/// 对话消息(迁移自 Tools.MyCommon)
/// </summary>
public sealed class ChatMessage
{
public string Role { get; set; }
public string Content { get; set; }
public string ThinkingContent { get; set; }
public bool IsStreaming { get; set; }
public DateTime Timestamp { get; set; } = DateTime.Now;
}
}
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
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