Files
Yi.Framework/Yi.Abp.Net8/module/ai-hub/Yi.Framework.AiHub.Domain/Managers/ChatManager.cs
chenchun bd3a9a5ce8 feat: 新增功能
- ChatManager:
  - 引入 System.Text.Json,用于将 agent thread 序列化与反序列化(示例:thread.Serialize(...) -> JsonSerializer.Deserialize -> agent.DeserializeThread)。
  - 增加示例:创建 OpenAIClient、初始化 agent、运行流式响应并处理更新。
  - 小幅格式和空行调整。
- AiChatService:
  - 为 Agent 发送接口 PostAgentSendAsync 增加注释与路由标记 HttpPost("ai-chat/agent/send")。

注意:提交中出现了硬编码的 API Key,请尽快改为从配置或机密管理中读取以防泄露。
2025-12-23 17:29:07 +08:00

105 lines
3.9 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
using System.ClientModel;
using System.Reflection;
using System.Text.Json;
using Dm.util;
using Microsoft.Agents.AI;
using Microsoft.Extensions.AI;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using ModelContextProtocol.Server;
using OpenAI;
using Volo.Abp.Domain.Services;
namespace Yi.Framework.AiHub.Domain.Managers;
public class ChatManager : DomainService
{
private readonly AiGateWayManager _aiGateWayManager;
private readonly ILoggerFactory _loggerFactory;
public ChatManager(AiGateWayManager aiGateWayManager, ILoggerFactory loggerFactory)
{
_aiGateWayManager = aiGateWayManager;
_loggerFactory = loggerFactory;
}
public async Task CompleteChatStreamAsync()
{
//token可以用户传进来
// HttpClient.DefaultProxy = new WebProxy("127.0.0.1:8888");
var modelId = "gpt-5.2-chat";
var client = new OpenAIClient(new ApiKeyCredential("xxx"),
new OpenAIClientOptions
{
Endpoint = new Uri("https://yxai.chat/v1"),
});
var agent = client.GetChatClient(modelId)
.AsIChatClient() // Converts a native OpenAI SDK ChatClient into a Microsoft.Extensions.AI.IChatClient
.CreateAIAgent("你是一个专业的网页ai助手");
var thread = agent.GetNewThread();
var tools = GetTools();
var chatOptions = new ChatOptions()
{
Tools = tools.Select(x => (AITool)x).ToList(),
ToolMode = ChatToolMode.Auto
};
await foreach (var update in agent.RunStreamingAsync("联网搜索一下,奥德赛第一中学学生会会长是谁", thread,
new ChatClientAgentRunOptions(chatOptions)))
{
// 检查每个更新中的内容
foreach (var content in update.Contents)
{
switch (content)
{
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;
}
}
}
string serializedJson = thread.Serialize(JsonSerializerOptions.Web).GetRawText();
JsonElement reloaded = JsonSerializer.Deserialize<JsonElement>(serializedJson, JsonSerializerOptions.Web);
var newThread = agent.DeserializeThread(reloaded, JsonSerializerOptions.Web);
}
private List<AIFunction> GetTools()
{
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)
{
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));
}
}
return mcpTools;
}
}