2025-12-23 17:08:42 +08:00
|
|
|
|
using System.ClientModel;
|
2025-12-23 17:40:00 +08:00
|
|
|
|
using System.Diagnostics.CodeAnalysis;
|
|
|
|
|
|
using System.Net;
|
2025-12-23 17:08:42 +08:00
|
|
|
|
using System.Reflection;
|
2025-12-23 17:29:07 +08:00
|
|
|
|
using System.Text.Json;
|
2025-12-23 17:08:42 +08:00
|
|
|
|
using Dm.util;
|
|
|
|
|
|
using Microsoft.Agents.AI;
|
|
|
|
|
|
using Microsoft.Extensions.AI;
|
2025-12-23 00:49:17 +08:00
|
|
|
|
using Microsoft.Extensions.DependencyInjection;
|
|
|
|
|
|
using Microsoft.Extensions.Logging;
|
2025-12-23 17:08:42 +08:00
|
|
|
|
using ModelContextProtocol.Server;
|
|
|
|
|
|
using OpenAI;
|
2025-12-23 17:40:00 +08:00
|
|
|
|
using OpenAI.Chat;
|
|
|
|
|
|
using OpenAI.Responses;
|
2025-12-23 00:49:17 +08:00
|
|
|
|
using Volo.Abp.Domain.Services;
|
|
|
|
|
|
|
|
|
|
|
|
namespace Yi.Framework.AiHub.Domain.Managers;
|
|
|
|
|
|
|
|
|
|
|
|
public class ChatManager : DomainService
|
|
|
|
|
|
{
|
|
|
|
|
|
private readonly AiGateWayManager _aiGateWayManager;
|
2025-12-23 17:08:42 +08:00
|
|
|
|
private readonly ILoggerFactory _loggerFactory;
|
2025-12-23 17:29:07 +08:00
|
|
|
|
|
2025-12-23 17:08:42 +08:00
|
|
|
|
public ChatManager(AiGateWayManager aiGateWayManager, ILoggerFactory loggerFactory)
|
2025-12-23 00:49:17 +08:00
|
|
|
|
{
|
|
|
|
|
|
_aiGateWayManager = aiGateWayManager;
|
2025-12-23 17:08:42 +08:00
|
|
|
|
_loggerFactory = loggerFactory;
|
2025-12-23 00:49:17 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2025-12-23 17:40:00 +08:00
|
|
|
|
|
2025-12-23 17:08:42 +08:00
|
|
|
|
public async Task CompleteChatStreamAsync()
|
2025-12-23 00:49:17 +08:00
|
|
|
|
{
|
2025-12-23 17:08:42 +08:00
|
|
|
|
//token可以用户传进来
|
2025-12-23 17:40:00 +08:00
|
|
|
|
// HttpClient.DefaultProxy = new WebProxy("127.0.0.1:8888");
|
|
|
|
|
|
var modelId = "gpt-5.2";
|
2025-12-23 17:29:07 +08:00
|
|
|
|
var client = new OpenAIClient(new ApiKeyCredential("xxx"),
|
|
|
|
|
|
new OpenAIClientOptions
|
|
|
|
|
|
{
|
|
|
|
|
|
Endpoint = new Uri("https://yxai.chat/v1"),
|
|
|
|
|
|
});
|
2025-12-23 17:08:42 +08:00
|
|
|
|
var agent = client.GetChatClient(modelId)
|
2025-12-23 17:29:07 +08:00
|
|
|
|
.CreateAIAgent("你是一个专业的网页ai助手");
|
|
|
|
|
|
|
2025-12-23 00:49:17 +08:00
|
|
|
|
|
2025-12-23 17:08:42 +08:00
|
|
|
|
var thread = agent.GetNewThread();
|
2025-12-23 00:49:17 +08:00
|
|
|
|
|
2025-12-23 17:08:42 +08:00
|
|
|
|
var tools = GetTools();
|
|
|
|
|
|
var chatOptions = new ChatOptions()
|
2025-12-23 00:49:17 +08:00
|
|
|
|
{
|
2025-12-23 17:08:42 +08:00
|
|
|
|
Tools = tools.Select(x => (AITool)x).ToList(),
|
|
|
|
|
|
ToolMode = ChatToolMode.Auto
|
|
|
|
|
|
};
|
2025-12-23 17:29:07 +08:00
|
|
|
|
|
2025-12-23 17:08:42 +08:00
|
|
|
|
await foreach (var update in agent.RunStreamingAsync("联网搜索一下,奥德赛第一中学学生会会长是谁", thread,
|
|
|
|
|
|
new ChatClientAgentRunOptions(chatOptions)))
|
2025-12-23 00:49:17 +08:00
|
|
|
|
{
|
2025-12-23 17:08:42 +08:00
|
|
|
|
// 检查每个更新中的内容
|
|
|
|
|
|
foreach (var content in update.Contents)
|
2025-12-23 00:49:17 +08:00
|
|
|
|
{
|
2025-12-23 17:08:42 +08:00
|
|
|
|
switch (content)
|
2025-12-23 00:49:17 +08:00
|
|
|
|
{
|
2025-12-23 17:08:42 +08:00
|
|
|
|
case FunctionCallContent functionCall:
|
|
|
|
|
|
Console.WriteLine();
|
|
|
|
|
|
Console.WriteLine(
|
|
|
|
|
|
$"🔧 工具调用开始: {functionCall.CallId},{functionCall.Name},{functionCall.Arguments}");
|
|
|
|
|
|
break;
|
|
|
|
|
|
case FunctionResultContent functionResult:
|
|
|
|
|
|
Console.WriteLine();
|
|
|
|
|
|
Console.WriteLine($"✅ 工具调用完成: {functionResult.CallId},{functionResult.Result}");
|
|
|
|
|
|
break;
|
|
|
|
|
|
case TextContent textContent:
|
|
|
|
|
|
Console.Write($"{textContent.Text}");
|
|
|
|
|
|
break;
|
|
|
|
|
|
case UsageContent usageContent:
|
|
|
|
|
|
Console.WriteLine();
|
|
|
|
|
|
Console.WriteLine($"✅ 用量统计: {usageContent.Details.TotalTokenCount}");
|
|
|
|
|
|
break;
|
2025-12-23 00:49:17 +08:00
|
|
|
|
}
|
2025-12-23 17:08:42 +08:00
|
|
|
|
}
|
2025-12-23 00:49:17 +08:00
|
|
|
|
}
|
2025-12-23 17:29:07 +08:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
string serializedJson = thread.Serialize(JsonSerializerOptions.Web).GetRawText();
|
|
|
|
|
|
JsonElement reloaded = JsonSerializer.Deserialize<JsonElement>(serializedJson, JsonSerializerOptions.Web);
|
|
|
|
|
|
var newThread = agent.DeserializeThread(reloaded, JsonSerializerOptions.Web);
|
2025-12-23 00:49:17 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2025-12-23 17:08:42 +08:00
|
|
|
|
|
|
|
|
|
|
private List<AIFunction> GetTools()
|
2025-12-23 00:49:17 +08:00
|
|
|
|
{
|
2025-12-23 17:08:42 +08:00
|
|
|
|
var toolClasses = typeof(YiFrameworkAiHubDomainModule).Assembly.GetTypes()
|
|
|
|
|
|
.Where(x => x.GetCustomAttribute<McpServerToolTypeAttribute>() is not null)
|
|
|
|
|
|
.ToList();
|
|
|
|
|
|
|
|
|
|
|
|
List<AIFunction> mcpTools = new List<AIFunction>();
|
|
|
|
|
|
foreach (var toolClass in toolClasses)
|
2025-12-23 00:49:17 +08:00
|
|
|
|
{
|
2025-12-23 17:08:42 +08:00
|
|
|
|
var instance = LazyServiceProvider.GetRequiredService(toolClass);
|
|
|
|
|
|
var toolMethods = toolClass.GetMethods()
|
|
|
|
|
|
.Where(y => y.GetCustomAttribute<McpServerToolAttribute>() is not null).ToList();
|
|
|
|
|
|
foreach (var toolMethod in toolMethods)
|
|
|
|
|
|
{
|
|
|
|
|
|
mcpTools.add(AIFunctionFactory.Create(toolMethod, instance));
|
|
|
|
|
|
}
|
2025-12-23 00:49:17 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2025-12-23 17:08:42 +08:00
|
|
|
|
return mcpTools;
|
2025-12-23 00:49:17 +08:00
|
|
|
|
}
|
|
|
|
|
|
}
|