using System.Text.Json;
using NewLife.Studio.AI.Models;
using NewLife.Log;
namespace NewLife.Studio.AI.ToolCalling;
/// <summary>AI 服务 — 管理对话历史和 Tool Calling 循环</summary>
public class AIService
{
private readonly IAIProvider _provider;
private readonly ToolRegistry _toolRegistry;
private readonly List<ChatMessage> _history = [];
private string? _systemPrompt;
public AIService(IAIProvider provider, ToolRegistry toolRegistry, string? systemPrompt = null)
{
_provider = provider;
_toolRegistry = toolRegistry;
_systemPrompt = systemPrompt;
if (_systemPrompt != null)
{
_history.Add(new ChatMessage { Role = "system", Content = _systemPrompt });
}
}
public IReadOnlyList<ChatMessage> History => _history.AsReadOnly();
/// <summary>发送用户消息,执行完整的 Tool Calling 循环</summary>
public async Task<string> ChatAsync(string userMessage, Action<ToolCall, ToolResult>? onToolCall = null)
{
_history.Add(new ChatMessage { Role = "user", Content = userMessage });
var tools = _toolRegistry.GetAllDefinitions();
for (int loop = 0; loop < 5; loop++) // 最多 5 轮
{
var request = new ChatRequest
{
Messages = [.._history],
Tools = tools.Count > 0 ? tools : null
};
var response = await _provider.ChatAsync(request);
var choice = response.Choices.FirstOrDefault();
if (choice == null)
break;
var msg = choice.Message;
// 检查是否有 tool_calls
if (msg.ToolCalls is { Count: > 0 })
{
// 添加 assistant 消息(带 tool_calls)
_history.Add(new ChatMessage
{
Role = "assistant",
Content = msg.Content,
ToolCalls = msg.ToolCalls
});
// 执行每个工具调用
foreach (var tc in msg.ToolCalls)
{
XTrace.WriteLine($"AI ToolCall: {tc.Function.Name}({tc.Function.Arguments})");
var result = await _toolRegistry.ExecuteAsync(tc);
onToolCall?.Invoke(tc, result);
_history.Add(new ChatMessage
{
Role = "tool",
ToolCallId = tc.Id,
Content = result.Error ?? result.Output
});
}
continue; // 继续循环,让 AI 处理工具结果
}
// 无 tool_calls,返回内容
if (msg.Content != null)
{
_history.Add(new ChatMessage { Role = "assistant", Content = msg.Content });
return msg.Content;
}
break;
}
return "AI 未返回有效响应";
}
public void ClearHistory()
{
_history.Clear();
if (_systemPrompt != null)
{
_history.Add(new ChatMessage { Role = "system", Content = _systemPrompt });
}
}
}
|