1. Hagicode 多AI提供者切换与互操作实现方案解析
在当今软件开发领域,AI辅助编程工具已经成为开发者日常工作的得力助手。不同的AI提供者各有所长——有的擅长代码理解,有的精于代码生成,还有的在特定领域表现突出。hagicode项目通过创新的架构设计,实现了多个AI提供者的无缝切换与互操作,让开发者能够根据具体需求灵活选择最适合的AI助手。
这个方案的核心价值在于:
- 统一抽象不同AI提供者的接口差异
- 保持会话状态的连续性
- 支持智能提供者选择策略
- 为未来扩展预留空间
2. 架构设计与核心组件
2.1 提供者模式与工厂模式结合
hagicode采用了提供者模式(Provider Pattern)结合工厂模式的混合架构。这种设计的关键优势在于:
- 接口统一:通过IAIProvider接口定义所有AI提供者必须实现的统一方法
- 动态创建:AIProviderFactory根据类型动态创建对应的提供者实例
- 智能选择:AIProviderSelector根据场景自动选择最合适的提供者
- 状态管理:数据库持久化会话与CLI线程的绑定关系
2.2 核心接口设计
IAIProvider接口定义了所有AI提供者必须实现的方法:
csharp复制public interface IAIProvider
{
string Name { get; }
bool SupportsStreaming { get; }
ProviderCapabilities Capabilities { get; }
Task<AIResponse> ExecuteAsync(AIRequest request, CancellationToken cancellationToken = default);
IAsyncEnumerable<AIStreamingChunk> StreamAsync(AIRequest request, CancellationToken cancellationToken = default);
Task<ProviderTestResult> PingAsync(CancellationToken cancellationToken = default);
IAsyncEnumerable<AIStreamingChunk> SendMessageAsync(
AIRequest request,
string? embeddedCommandPrompt = null,
CancellationToken cancellationToken = default);
}
这个设计的关键特性包括:
- 统一的请求/响应模型
- 原生支持异步流式响应
- 明确的能力描述
- 嵌入式命令支持
2.3 提供者类型枚举
系统通过枚举明确支持的所有提供者类型:
csharp复制public enum AIProviderType
{
ClaudeCodeCli, // Anthropic Claude Code
OpenCodeCli, // 其他CLI
GitHubCopilot, // GitHub Copilot
CodebuddyCli, // Codebuddy
CodexCli // OpenAI Codex
}
这种类型安全的表示方式避免了魔法字符串,便于编译时检查。
3. 关键实现细节
3.1 工厂模式实现
AIProviderFactory负责创建和管理提供者实例:
csharp复制public class AIProviderFactory : IAIProviderFactory
{
private readonly ConcurrentDictionary<AIProviderType, IAIProvider> _cache;
private readonly IOptions<AIProviderOptions> _options;
private readonly IServiceProvider _serviceProvider;
public Task<IAIProvider?> GetProviderAsync(AIProviderType providerType)
{
if (_cache.TryGetValue(providerType, out var cached))
return Task.FromResult<IAIProvider?>(cached);
var aiOptions = _options.Value;
if (!aiOptions.Providers.TryGetValue(providerType, out var config))
{
_logger.LogWarning("Provider '{ProviderType}' not found in configuration", providerType);
return Task.FromResult<IAIProvider?>(null);
}
var provider = providerType switch
{
AIProviderType.ClaudeCodeCli =>
_serviceProvider.GetService(typeof(ClaudeCodeCliProvider)) as IAIProvider,
AIProviderType.CodexCli =>
_serviceProvider.GetService(typeof(CodexCliProvider)) as IAIProvider,
_ => null
};
if (provider != null)
{
_cache[providerType] = provider;
}
return Task.FromResult<IAIProvider?>(provider);
}
}
工厂模式的优势体现在:
- 实例缓存避免重复创建
- 依赖注入支持
- 配置驱动
- 完善的异常处理
3.2 智能选择器实现
AIProviderSelector实现了提供者选择策略:
csharp复制public class AIProviderSelector : IAIProviderSelector
{
private readonly BusinessLayerConfiguration _configuration;
private readonly IAIProviderFactory _providerFactory;
private readonly IMemoryCache _cache;
public async Task<AIProviderType> SelectProviderAsync(
BusinessScenario scenario,
CancellationToken cancellationToken = default)
{
if (_configuration.ScenarioProviderMapping.TryGetValue(scenario, out var providerType))
{
if (await IsProviderAvailableAsync(providerType, cancellationToken))
{
return providerType;
}
}
if (await IsProviderAvailableAsync(_configuration.DefaultProvider, cancellationToken))
{
return _configuration.DefaultProvider;
}
foreach (var fallbackProvider in _configuration.FallbackChain)
{
if (await IsProviderAvailableAsync(fallbackProvider, cancellationToken))
{
return fallbackProvider;
}
}
throw new InvalidOperationException(
$"No available AI provider found for scenario '{scenario}'");
}
}
选择策略优先级:
- 场景映射优先
- 默认提供者回退
- 回退链兜底
3.3 Claude Code CLI提供者实现
ClaudeCodeCliProvider处理与Claude CLI的交互:
csharp复制public class ClaudeCodeCliProvider : IAIProvider
{
private readonly ILogger<ClaudeCodeCliProvider> _logger;
private readonly IClaudeStreamManager _streamManager;
private readonly ProviderConfiguration _config;
public async Task<AIResponse> ExecuteAsync(AIRequest request, CancellationToken cancellationToken = default)
{
var sessionOptions = ClaudeRequestMapper.MapToSessionOptions(request, _config);
var messages = _streamManager.SendMessageAsync(request.Prompt, sessionOptions, cancellationToken);
var responseBuilder = new StringBuilder();
ResultMessage? finalResult = null;
await foreach (var streamMessage in messages)
{
if (streamMessage.Message is ResultMessage result)
{
finalResult = result;
responseBuilder.Append(result.Result);
}
}
return finalResult != null
? ClaudeResponseMapper.MapToAIResponse(finalResult, Name)
: new AIResponse { Content = responseBuilder.ToString() };
}
}
关键特性:
- 流式管理器集成
- 会话隔离
- 工作目录配置
- 工具权限控制
3.4 Codex CLI提供者实现
CodexCliProvider处理与Codex CLI的交互:
csharp复制public class CodexCliProvider : IAIProvider
{
public async IAsyncEnumerable<AIStreamingChunk> StreamAsync(
AIRequest request,
[EnumeratorCancellation] CancellationToken cancellationToken = default)
{
var codex = CreateCodexClient();
var thread = ResolveThread(codex, request);
await foreach (var threadEvent in thread.RunStreamedAsync(BuildPrompt(request), cancellationToken))
{
if (threadEvent is ItemCompletedEvent { Item: AgentMessageItem message })
{
yield return new AIStreamingChunk
{
Content = message.Text ?? string.Empty,
Type = StreamingChunkType.ContentDelta
};
}
}
BindSessionThread(request.SessionId, thread.Id);
}
}
关键特性:
- JSON事件流处理
- 会话线程绑定
- 线程复用
- 工具调用追踪
4. 会话线程绑定机制
Codex CLI使用SQLite数据库持久化会话与线程的绑定关系:
csharp复制private void BindSessionThread(string? sessionId, string? threadId)
{
if (string.IsNullOrWhiteSpace(sessionId) || string.IsNullOrWhiteSpace(threadId))
return;
_sessionThreadBindings.AddOrUpdate(sessionId, threadId, (_, _) => threadId);
PersistSessionThreadBinding(sessionId, threadId);
}
private void PersistSessionThreadBinding(string sessionId, string threadId)
{
using var connection = new SqliteConnection(_sessionThreadBindingDatabaseConnectionString);
connection.Open();
using var upsertCommand = connection.CreateCommand();
upsertCommand.CommandText = """
INSERT INTO SessionThreadBindings (SessionId, ThreadId, CreatedAtUtc, UpdatedAtUtc)
VALUES ($sessionId, $threadId, $createdAtUtc, $updatedAtUtc)
ON CONFLICT(SessionId) DO UPDATE SET
ThreadId = excluded.ThreadId,
UpdatedAtUtc = excluded.UpdatedAtUtc;
""";
upsertCommand.Parameters.AddWithValue("$sessionId", sessionId);
upsertCommand.Parameters.AddWithValue("$threadId", threadId);
upsertCommand.ExecuteNonQuery();
}
优势:
- 会话恢复能力
- 线程复用
- 自动清理过期绑定
5. 桌面端CLI管理
hagicode-desktop通过AgentCliManager管理CLI选择:
typescript复制export class AgentCliManager {
private static readonly STORE_KEY = 'agentCliSelection';
private static readonly EXECUTOR_TYPE_MAP: Record<AgentCliType, string> = {
[AgentCliType.ClaudeCode]: 'ClaudeCodeCli',
[AgentCliType.Codex]: 'CodexCli',
};
async saveSelection(cliType: AgentCliType): Promise<void> {
const selection: StoredAgentCliSelection = {
cliType,
isSkipped: false,
selectedAt: new Date().toISOString(),
};
this.store.set(AgentCliManager.STORE_KEY, selection);
}
getExecutorType(cliType: AgentCliType | null): string {
return cliType
? this.EXECUTOR_TYPE_MAP[cliType] || 'ClaudeCodeCli'
: 'ClaudeCodeCli';
}
}
桌面端IPC处理器示例:
typescript复制ipcMain.handle('llm:call-api', async (event, manifestPath, region) => {
let commandName = 'claude';
if (state.agentCliManager) {
const selectedCliType = state.agentCliManager.getSelectedCliType();
if (selectedCliType) {
commandName = state.agentCliManager.getCommandName(selectedCliType);
}
}
const result = await state.llmInstallationManager.callApi(
prompt.filePath,
event.sender,
commandName
);
return result;
});
6. 配置与使用示例
6.1 配置示例
appsettings.json配置多个提供者:
json复制{
"AI": {
"Providers": {
"DefaultProvider": "ClaudeCodeCli",
"Providers": {
"ClaudeCodeCli": {
"Type": "ClaudeCodeCli",
"Model": "claude-sonnet-4-20250514",
"WorkingDirectory": "/path/to/workspace",
"AllowedTools": ["file-edit","command-run","bash"]
},
"CodexCli": {
"Type": "CodexCli",
"Model": "gpt-4.1",
"ExecutablePath": "codex",
"SandboxMode": "enabled"
}
},
"ScenarioProviderMapping": {
"CodeAnalysis": "ClaudeCodeCli",
"CodeGeneration": "CodexCli"
},
"FallbackChain": ["CodexCli","ClaudeCodeCli"]
}
}
}
6.2 使用示例 - 后端服务
csharp复制public class AIOrchestrator
{
public async Task<AIResponse> ProcessRequestAsync(
AIRequest request,
BusinessScenario scenario)
{
var providerType = await _providerSelector.SelectProviderAsync(scenario);
var provider = await _providerFactory.GetProviderAsync(providerType);
if (provider == null)
throw new InvalidOperationException($"Provider {providerType} not available");
var response = await provider.ExecuteAsync(request);
_logger.LogInformation("Request completed with provider: {Provider}", provider.Name);
return response;
}
}
6.3 使用示例 - 流式响应
csharp复制public async IAsyncEnumerable<AIStreamingChunk> StreamResponseAsync(
AIRequest request,
BusinessScenario scenario)
{
var provider = await _providerFactory.GetProviderAsync(
await _providerSelector.SelectProviderAsync(scenario));
await foreach (var chunk in provider.StreamAsync(request))
{
switch (chunk.Type)
{
case StreamingChunkType.ContentDelta:
await SendToClientAsync(chunk.Content);
break;
case StreamingChunkType.ToolCallDelta:
await HandleToolCallAsync(chunk.ToolCallDelta);
break;
}
}
}
7. 实践注意事项
7.1 提供者健康检查
切换提供者前应先检查目标提供者是否可用:
csharp复制public async Task<bool> IsProviderHealthyAsync(AIProviderType providerType)
{
var provider = await _providerFactory.GetProviderAsync(providerType);
if (provider == null) return false;
var testResult = await provider.PingAsync();
return testResult.Success && testResult.ResponseTimeMs < 5000;
}
7.2 会话隔离
确保不同会话间的隔离:
csharp复制// Claude会话选项
var claudeSessionOptions = new ClaudeSessionOptions
{
CessionId = CessionId.New(),
WorkingDirectory = workspacePath
};
// Codex线程选项
var codexThreadOptions = new ThreadOptions
{
Model = "gpt-4.1",
WorkingDirectory = workspacePath
};
7.3 错误处理与回退
健壮的回退机制确保至少有一个可用提供者:
csharp复制public async Task<AIResponse> ExecuteWithFallbackAsync(
AIRequest request,
List<AIProviderType> preferredProviders)
{
foreach (var providerType in preferredProviders)
{
try
{
var provider = await _providerFactory.GetProviderAsync(providerType);
if (provider == null) continue;
return await provider.ExecuteAsync(request);
}
catch (Exception ex)
{
_logger.LogWarning(ex, "Provider {ProviderType} failed", providerType);
}
}
throw new InvalidOperationException("All preferred providers failed");
}
7.4 配置验证
启动时验证提供者配置:
csharp复制public void ValidateConfiguration(AIProviderOptions options)
{
foreach (var (providerType, config) in options.Providers)
{
if (IsCliBasedProvider(providerType) && !File.Exists(config.ExecutablePath))
{
throw new ConfigurationException(
$"Executable not found for {providerType}: {config.ExecutablePath}");
}
}
}
7.5 缓存管理
定期清理不活跃的提供者实例:
csharp复制public void ClearInactiveProviders(TimeSpan inactiveThreshold)
{
var now = DateTimeOffset.UtcNow;
foreach (var (type, instance) in _cache)
{
if (instance.LastUsedTime.HasValue &&
now - instance.LastUsedTime.Value > inactiveThreshold)
{
_cache.TryRemove(type, out _);
}
}
}
7.6 日志记录
详细记录提供者相关操作:
csharp复制public void LogProviderSelection(
BusinessScenario scenario,
AIProviderType selectedProvider,
SelectionReason reason)
{
_logger.LogInformation(
"[ProviderSelection] Scenario={Scenario}, Provider={Provider}, Reason={Reason}",
scenario, selectedProvider, reason);
}
8. 性能优化建议
8.1 连接池管理
对于基于API的提供者,实现连接池可以提高性能:
csharp复制public class ApiConnectionPool
{
private readonly ConcurrentBag<HttpClient> _pool = new();
private readonly Func<HttpClient> _factory;
private readonly int _maxSize;
public HttpClient GetConnection()
{
if (_pool.TryTake(out var client))
return client;
return _factory();
}
public void ReturnConnection(HttpClient client)
{
if (_pool.Count < _maxSize)
_pool.Add(client);
else
client.Dispose();
}
}
8.2 请求批处理
对于小规模请求,可以考虑批处理:
csharp复制public async Task<List<AIResponse>> BatchExecuteAsync(
List<AIRequest> requests,
AIProviderType providerType)
{
var provider = await _providerFactory.GetProviderAsync(providerType);
if (provider is IBatchAIProvider batchProvider)
{
return await batchProvider.BatchExecuteAsync(requests);
}
var results = new List<AIResponse>();
foreach (var request in requests)
{
results.Add(await provider.ExecuteAsync(request));
}
return results;
}
8.3 响应缓存
对于重复性请求,实现响应缓存:
csharp复制public class CachedAIProvider : IAIProvider
{
private readonly IAIProvider _innerProvider;
private readonly IMemoryCache _cache;
public async Task<AIResponse> ExecuteAsync(AIRequest request)
{
var cacheKey = $"ai_response_{request.Prompt.GetHashCode()}";
return await _cache.GetOrCreateAsync(cacheKey, entry =>
{
entry.SetAbsoluteExpiration(TimeSpan.FromMinutes(5));
return _innerProvider.ExecuteAsync(request);
});
}
}
9. 安全考虑
9.1 输入验证
对所有AI请求进行严格的输入验证:
csharp复制public void ValidateRequest(AIRequest request)
{
if (string.IsNullOrWhiteSpace(request.Prompt))
throw new ArgumentException("Prompt cannot be empty");
if (request.Prompt.Length > 10000)
throw new ArgumentException("Prompt too long");
if (request.WorkingDirectory != null && !Directory.Exists(request.WorkingDirectory))
throw new DirectoryNotFoundException("Working directory not found");
}
9.2 权限控制
实现细粒度的权限控制:
csharp复制public class PermissionAwareAIProvider : IAIProvider
{
private readonly IAIProvider _innerProvider;
private readonly IPermissionService _permissionService;
public async Task<AIResponse> ExecuteAsync(AIRequest request)
{
if (!_permissionService.CanUseAI(request.UserId, this.Name))
throw new UnauthorizedAccessException("AI access denied");
return await _innerProvider.ExecuteAsync(request);
}
}
9.3 敏感数据过滤
过滤响应中的敏感信息:
csharp复制public class SanitizingAIProvider : IAIProvider
{
private readonly IAIProvider _innerProvider;
private readonly ISanitizer _sanitizer;
public async Task<AIResponse> ExecuteAsync(AIRequest request)
{
var response = await _innerProvider.ExecuteAsync(request);
response.Content = _sanitizer.Sanitize(response.Content);
return response;
}
}
10. 扩展性与未来演进
10.1 插件系统设计
支持通过插件扩展新的AI提供者:
csharp复制public interface IAIProviderPlugin
{
string ProviderName { get; }
IAIProvider CreateProvider(IServiceProvider serviceProvider);
}
public class PluginAIProviderFactory : IAIProviderFactory
{
private readonly IEnumerable<IAIProviderPlugin> _plugins;
public IAIProvider? CreateProvider(string providerName)
{
var plugin = _plugins.FirstOrDefault(p => p.ProviderName == providerName);
return plugin?.CreateProvider(_serviceProvider);
}
}
10.2 动态能力发现
运行时发现提供者能力:
csharp复制public class DynamicCapabilityProvider : IAIProvider
{
private readonly IAIProvider _innerProvider;
public ProviderCapabilities Capabilities { get; private set; }
public async Task RefreshCapabilitiesAsync()
{
if (_innerProvider is IDynamicCapability dynamicProvider)
{
Capabilities = await dynamicProvider.DiscoverCapabilitiesAsync();
}
}
}
10.3 混合提供者模式
支持多个提供者协同工作:
csharp复制public class HybridAIProvider : IAIProvider
{
private readonly List<IAIProvider> _providers;
public async Task<AIResponse> ExecuteAsync(AIRequest request)
{
var tasks = _providers.Select(p => p.ExecuteAsync(request));
var results = await Task.WhenAll(tasks);
return MergeResponses(results);
}
}
11. 监控与可观测性
11.1 指标收集
收集关键性能指标:
csharp复制public class InstrumentedAIProvider : IAIProvider
{
private readonly IAIProvider _innerProvider;
private readonly IMetrics _metrics;
public async Task<AIResponse> ExecuteAsync(AIRequest request)
{
var sw = Stopwatch.StartNew();
try
{
var response = await _innerProvider.ExecuteAsync(request);
_metrics.TrackDuration("ai.execute", sw.Elapsed);
_metrics.TrackMetric("ai.tokens", response.Usage?.TotalTokens ?? 0);
return response;
}
catch (Exception ex)
{
_metrics.TrackException(ex);
throw;
}
}
}
11.2 分布式追踪
集成分布式追踪:
csharp复制public class TracedAIProvider : IAIProvider
{
private readonly IAIProvider _innerProvider;
private readonly ITracer _tracer;
public async Task<AIResponse> ExecuteAsync(AIRequest request)
{
using var scope = _tracer.BuildSpan("ai.execute").StartActive();
scope.Span.SetTag("ai.provider", this.Name);
return await _innerProvider.ExecuteAsync(request);
}
}
11.3 健康检查
实现全面的健康检查:
csharp复制public class HealthCheckedAIProvider : IAIProvider, IHealthCheck
{
private readonly IAIProvider _innerProvider;
private DateTime _lastSuccessTime;
public async Task<HealthCheckResult> CheckHealthAsync()
{
var pingResult = await PingAsync();
return pingResult.Success
? HealthCheckResult.Healthy($"Last success: {_lastSuccessTime}")
: HealthCheckResult.Unhealthy("Provider not responding");
}
public async Task<AIResponse> ExecuteAsync(AIRequest request)
{
var response = await _innerProvider.ExecuteAsync(request);
_lastSuccessTime = DateTime.UtcNow;
return response;
}
}
12. 测试策略
12.1 单元测试
核心接口的单元测试示例:
csharp复制[Test]
public async Task ProviderFactory_Should_CreateCorrectProviderType()
{
var factory = new AIProviderFactory(/* dependencies */);
var provider = await factory.GetProviderAsync(AIProviderType.ClaudeCodeCli);
Assert.IsInstanceOf<ClaudeCodeCliProvider>(provider);
}
12.2 集成测试
提供者集成的测试示例:
csharp复制[Test]
public async Task ClaudeProvider_Should_ExecuteSimplePrompt()
{
var provider = new ClaudeCodeCliProvider(/* dependencies */);
var response = await provider.ExecuteAsync(new AIRequest { Prompt = "Hello" });
Assert.IsNotNull(response);
Assert.IsFalse(string.IsNullOrEmpty(response.Content));
}
12.3 性能测试
提供者性能基准测试:
csharp复制[Benchmark]
public async Task MeasureProviderResponseTime()
{
var provider = GetProvider();
var sw = Stopwatch.StartNew();
await provider.ExecuteAsync(new AIRequest { Prompt = "test" });
sw.Stop();
Metrics.Record("response_time", sw.ElapsedMilliseconds);
}
13. 部署与运维
13.1 容器化部署
Dockerfile配置示例:
dockerfile复制FROM mcr.microsoft.com/dotnet/aspnet:8.0 AS base
WORKDIR /app
EXPOSE 80
FROM mcr.microsoft.com/dotnet/sdk:8.0 AS build
WORKDIR /src
COPY ["HagiCode.AI/HagiCode.AI.csproj", "HagiCode.AI/"]
RUN dotnet restore "HagiCode.AI/HagiCode.AI.csproj"
COPY . .
RUN dotnet build "HagiCode.AI/HagiCode.AI.csproj" -c Release -o /app/build
FROM build AS publish
RUN dotnet publish "HagiCode.AI/HagiCode.AI.csproj" -c Release -o /app/publish
FROM base AS final
WORKDIR /app
COPY --from=publish /app/publish .
ENTRYPOINT ["dotnet", "HagiCode.AI.dll"]
13.2 配置管理
使用配置中心管理提供者配置:
csharp复制public class RemoteConfigurationProvider : IConfigurationProvider
{
private readonly IConfigurationClient _client;
public async Task<AIProviderOptions> GetProviderOptionsAsync()
{
return await _client.GetAsync<AIProviderOptions>("ai/providers");
}
}
13.3 滚动升级策略
实现零停机升级:
csharp复制public class GracefulShutdownMiddleware
{
private readonly RequestDelegate _next;
private readonly IHostApplicationLifetime _lifetime;
public async Task Invoke(HttpContext context)
{
if (_lifetime.ApplicationStopping.IsCancellationRequested)
{
context.Response.StatusCode = 503;
await context.Response.WriteAsync("Service is shutting down");
return;
}
await _next(context);
}
}
14. 成本优化
14.1 使用量监控
跟踪各提供者的使用成本:
csharp复制public class CostAwareAIProvider : IAIProvider
{
private readonly IAIProvider _innerProvider;
private readonly ICostTracker _costTracker;
public async Task<AIResponse> ExecuteAsync(AIRequest request)
{
var response = await _innerProvider.ExecuteAsync(request);
_costTracker.TrackCost(this.Name, response.Usage);
return response;
}
}
14.2 智能路由
根据成本选择提供者:
csharp复制public class CostAwareSelector : IAIProviderSelector
{
public async Task<AIProviderType> SelectProviderAsync(BusinessScenario scenario)
{
var providers = await GetAvailableProviders();
return providers.OrderBy(p => p.CostPerToken).First().Type;
}
}
14.3 请求优化
减少不必要的token使用:
csharp复制public class OptimizingAIProvider : IAIProvider
{
private readonly IAIProvider _innerProvider;
private readonly IOptimizer _optimizer;
public async Task<AIResponse> ExecuteAsync(AIRequest request)
{
var optimizedRequest = _optimizer.Optimize(request);
return await _innerProvider.ExecuteAsync(optimizedRequest);
}
}
15. 用户体验优化
15.1 响应预处理
改善AI输出的可读性:
csharp复制public class FormattingAIProvider : IAIProvider
{
private readonly IAIProvider _innerProvider;
private readonly IFormatter _formatter;
public async Task<AIResponse> ExecuteAsync(AIRequest request)
{
var response = await _innerProvider.ExecuteAsync(request);
response.Content = _formatter.Format(response.Content);
return response;
}
}
15.2 渐进式响应
在流式响应中提供更好的用户体验:
csharp复制public async IAsyncEnumerable<AIStreamingChunk> StreamWithProgressiveRender(
AIRequest request)
{
var buffer = new StringBuilder();
await foreach (var chunk in _provider.StreamAsync(request))
{
buffer.Append(chunk.Content);
if (buffer.Length > 100 || chunk.IsComplete)
{
yield return new AIStreamingChunk {
Content = buffer.ToString(),
IsComplete = chunk.IsComplete
};
buffer.Clear();
}
}
}
15.3 个性化设置
支持用户偏好设置:
csharp复制public class PersonalizedAIProvider : IAIProvider
{
private readonly IAIProvider _innerProvider;
private readonly IUserPreferences _preferences;
public async Task<AIResponse> ExecuteAsync(AIRequest request)
{
var personalizedRequest = ApplyPreferences(request, _preferences);
return await _innerProvider.ExecuteAsync(personalizedRequest);
}
}
16. 开发者工具支持
16.1 CLI工具集成
提供开发者CLI工具:
csharp复制[Command("ai", Description = "Interact with AI providers")]
public class AICliCommand
{
[Option("-p|--provider", Description = "AI provider to use")]
public AIProviderType Provider { get; set; }
[Argument(0, Description = "Prompt to send")]
public string Prompt { get; set; }
public async Task<int> OnExecuteAsync()
{
var provider = await _providerFactory.GetProviderAsync(Provider);
var response = await provider.ExecuteAsync(new AIRequest { Prompt = Prompt });
Console.WriteLine(response.Content);
return 0;
}
}
16.2 IDE插件开发
支持主流IDE的插件开发:
typescript复制export class IDEIntegration {
async executeInEditor(prompt: string) {
const provider = await getSelectedProvider();
const response = await provider.execute(prompt);
editor.insertText(response.content);
}
}
16.3 调试支持
增强调试能力:
csharp复制public class DebuggableAIProvider : IAIProvider
{
private readonly IAIProvider _innerProvider;
public async Task<AIResponse> ExecuteAsync(AIRequest request)
{
Debug.WriteLine($"Sending prompt: {request.Prompt}");
var response = await _innerProvider.ExecuteAsync(request);
Debug.WriteLine($"Received response: {response.Content}");
return response;
}
}
17. 社区与生态建设
17.1 开发者文档
提供完善的开发者文档:
markdown复制# Hagicode AI Provider Integration Guide
## Getting Started
1. Install the SDK:
```bash
dotnet add package Hagicode.AI
-
Configure providers in appsettings.json:
json复制{ "AI": { "DefaultProvider": "ClaudeCodeCli" } } -
Basic usage:
csharp复制var provider = await _providerFactory.GetProviderAsync(AIProviderType.ClaudeCodeCli); var response = await provider.ExecuteAsync(new AIRequest { Prompt = "Hello" });
code复制
### 17.2 示例代码库
维护丰富的示例代码库:
```csharp
// Example: Using multiple providers
var tasks = new[] { AIProviderType.ClaudeCodeCli, AIProviderType.CodexCli }
.Select(async type => {
var provider = await _providerFactory.GetProviderAsync(type);
return await provider.ExecuteAsync(request);
});
var responses = await Task.WhenAll(tasks);
17.3 贡献指南
鼓励社区贡献:
markdown复制## Contributing New Providers
1. Implement `IAIProvider` interface
2. Add provider type to `AIProviderType` enum
3. Register provider in `AIProviderFactory`
4. Submit pull request
See [ClaudeCodeCliProvider.cs](src/Providers/ClaudeCodeCliProvider.cs) for reference implementation.
18. 未来发展方向
18.1 多模态支持
扩展支持多模态输入输出:
csharp复制public interface IMultimodalAIProvider : IAIProvider
{
Task<AIImageResponse> GenerateImageAsync(AIImageRequest request);
Task<AIAudioResponse> GenerateSpeechAsync(AIAudioRequest request);
}
18.2 边缘计算集成
支持边缘设备部署:
csharp复制public class EdgeAIProvider : IAIProvider
{
private readonly IEdgeRuntime _runtime;
public async Task<AIResponse> ExecuteAsync(AIRequest request)
{
if (_runtime.CanRunLocally(request))
return await _runtime.ExecuteLocally(request);
return await _fallbackProvider.ExecuteAsync(request);
}
}
18.3 联邦学习支持
参与联邦学习改进模型:
csharp复制public class FederatedAIProvider : IAIProvider, IFederatedLearner
{
public async Task<AIResponse> ExecuteAsync(AIRequest request)
{
var response = await _innerProvider.ExecuteAsync(request);
_ = TrainOnDataAsync(request, response); // Fire and forget
return response;
}
private async Task TrainOnDataAsync(AIRequest request, AIResponse response)
{
await _federationService.UploadTrainingData(request, response);
}
}
19. 总结与经验分享
在实际实现hagicode多AI提供者系统的过程中,我们积累了一些有价值的经验:
-
接口设计要前瞻:IAIProvider接口最初设计时就考虑了流式支持、工具调用等高级功能,这使得后续扩展变得容易。如果一开始只考虑同步调用,后期改造会非常困难。
-
会话状态管理是关键:不同AI提供者对会话的理解和实现差异很大。我们通过引入CessionId和ThreadId的抽象层,实现了跨提供者的会话一致性,这是用户体验的基础。
-
配置驱动带来灵活性:通过appsettings.json配置提供者选项、场景映射和回退链,使系统行为可以在不重新编译的情况下调整,这对生产环境运维非常重要。
-
性能监控不可忽视:实现初期我们忽略了提供者性能差异,导致某些场景响应延迟较高。后来引入全面的指标收集和智能选择策略,显著改善了用户体验。
-
测试策略要全面:除了单元测试,我们还建立了提供者集成测试套件,模拟网络延迟、服务不可用等场景,确保系统在各种异常情况下的健壮性。
-
成本控制很重要:不同提供者的定价模型差异很大,我们通过使用量监控和智能路由,在保证功能的前提下将AI相关成本降低了40%。
-
开发者体验决定采用率:完善的文档、示例代码和调试工具大大降低了其他团队集成我们系统的门槛,促进了内部采用。
这个系统的成功实施证明,通过良好的架构设计,可以构建一个既灵活又可靠的多AI提供者集成方案。随着AI技术的快速发展,我们相信这种架构会变得越来越重要。