Как унифицированно интегрировать GPT, Claude и другие ИИ-модели с помощью Copilot CLI
Как унифицированно интегрировать GPT, Claude и другие ИИ-модели с помощью Copilot CLI
В разработке ИИ-приложений, как использовать единый интерфейс для интеграции различных моделей, таких как GPT, Claude? В этой статье мы делимся дизайном системы поставщиков ИИ на основе архитектуры Orleans Grain, а также практическим опытом интеграции с GitHub Copilot CLI.
Предпосылки
В современной разработке ИИ-приложений интеграция последних моделей GPT является ключевой потребностью для многих разработчиков. GitHub Copilot CLI — это мощный инструмент, который поддерживает не только серию моделей GPT от OpenAI (таких как GPT-4, GPT-5), но и другие популярные ИИ-модели, такие как Claude. Через Copilot CLI разработчики могут вызывать различные ИИ-модели, используя унифицированный интерфейс командной строки, без необходимости отдельно реализовывать сложную логику интеграции для каждой модели.
Это, по сути, старая проблема. Нужно написать логику вызова для каждой модели — это слёзы. В конце концов, когда кода много, всем становится надоедающим. Вместо того чтобы повторно изобретать колесо, лучше найти единый интерфейс, который справится со всем. Copilot CLI — именно такая сущность — вы просто вызываете, а остальное оставляете ему.
Ключевая ценность:
- Единый CLI-интерфейс для доступа к различным ИИ-моделям
- Поддержка управления сессиями и сохранения контекста
- Встроенная возможность вызова инструментов (операции с файлами, Git-операции и т.д.)
- Поддержка потоковых ответов и вывода в реальном времени
О HagiCode
Решение, представленное в этой статье, основано на нашем практическом опыте в проекте HagiCode. HagiCode — это проект ИИ-помощника для программирования. В процессе разработки мы столкнулись с вызовом одновременной поддержки различных ИИ-моделей — одни пользователи привыкли использовать GPT-4, другие предпочитают Claude, а некоторые хотят попробовать новейший GPT-5. Если реализовать отдельную логику вызова для каждой модели, код станет трудным в обслуживании. Благодаря унифицированному интерфейсу Copilot CLI мы успешно решили эту проблему поддержки множественных моделей.
Проще говоря, вкусы пользователей разнообразны, и всем угодить сложно. Кто-то любит GPT, кто-то предпочитает Claude, а кто-то обязательно хочет использовать новейший GPT-5. Мы просто хотим, чтобы каждый мог использовать свою любимую модель — в конце концов, самое главное — это удовольствие.
Дизайн системной архитектуры
Мы реализовали масштабируемую систему поставщиков ИИ через архитектуру Orleans Grain. Общая архитектура выглядит следующим образом:
┌─────────────────┐│ Фронтенд/клиент│└────────┬────────┘ │ ▼┌─────────────────────────────────┐│ IGitHubCopilotGrain (уровень ││ интерфейса) ││ - ExecuteCommandStreamAsync ││ - RunEditAsync ││ - CancelAsync │└────────┬────────────────────────┘ │ ▼┌─────────────────────────────────┐│ GitHubCopilotGrain (уровень ││ реализации) ││ - Управление состоянием ││ - Привязка сессии ││ - Отображение ответов │└────────┬────────────────────────┘ │ ▼┌─────────────────────────────────┐│ CopilotAIProvider (уровень ││ поставщика) ││ - Парсинг конфигурации ││ - Управление разрешениями ││ - Потоковая обработка │└────────┬────────────────────────┘ │ ▼┌─────────────────────────────────┐│ HagiCode.Libs (общая среда ││ выполнения) ││ - Управление процессами ││ Copilot CLI ││ - Парсинг протокола сообщений ││ - Сохранение сессии │└─────────────────────────────────┘Преимущество этой архитектуры в чётком разделении слоёв и единой ответственности. Уровень интерфейса определяет единый контракт ИИ-сервиса, уровень реализации обрабатывает распределённое управление состоянием Orleans, уровень поставщика инкапсулирует детали взаимодействия с Copilot CLI, а базовая среда выполнения отвечает за связь с процессом CLI.
Проще говоря, нужно чётко разделить задачи — каждый должен делать своё дело, не смешивая всё. В конце концов, как только код становится запутанным, его потом трудно изменить.
Анализ ключевых компонентов
1. GitHubCopilotGrain: интерфейс распределённого ИИ-сервиса
Как реализация Orleans Grain, GitHubCopilotGrain предоставляет возможности распределённого ИИ-сервиса:
public interface IGitHubCopilotGrain : IGrainWithStringKey{ /// <summary> /// Выполняет команду и возвращает ответ потоком /// </summary> Task<IAsyncEnumerable<GitHubCopilotResponse>> ExecuteCommandStreamAsync( string command, string? heroId = null, CancellationToken token = default, string? executionMessageId = null, string? systemMessage = null, Dictionary<string, string>? requestSettings = null);
/// <summary> /// Выполняет операцию редактирования /// </summary> Task<IAsyncEnumerable<GitHubCopilotResponse>> RunEditAsync( string editCommand, string? heroId = null, CancellationToken token = default);
/// <summary> /// Отменяет текущее выполнение /// </summary> Task CancelAsync(string heroId);}Ключевые моменты дизайна:
- Использование
IAsyncEnumerableдля поддержки потоковых ответов, избегая длительного ожидания - Реализация изоляции состояния на уровне сессии через
heroId - Поддержка передачи
requestSettingsдля динамической настройки параметров модели
2. CopilotAIProvider: основная реализация поставщика
CopilotAIProvider — это ядро всего решения, инкапсулирующее всю логику взаимодействия с Copilot CLI:
public class CopilotAIProvider : IAIProvider, IVersionedAIProvider{ private readonly CopilotOptions _options; private readonly ICopilotProcessExecutor _executor;
public async IAsyncEnumerable<AIStreamingChunk> SendMessageAsync( AIRequest request, string? embeddedCommandPrompt = null, [EnumeratorCancellation] CancellationToken cancellationToken = default) { // Создаём параметры выполнения var options = new CopilotOptions { Model = request.Model ?? _options.Model, SessionId = request.Options?.Settings?.GetValueOrDefault("copilotSessionId"), Timeout = _options.Timeout, PermissionMode = request.OperationType == AIOperationType.Edit ? CopilotPermissionMode.BypassPermissions : CopilotPermissionMode.Default };
// Выполняем команду и обрабатываем ответ потоком await foreach (var message in _executor.ExecuteAsync( options, request.Prompt, cancellationToken)) { yield return BuildChunk(message); } }}Ключевые особенности:
- Механизм автоматического повтора:обработка временных сетевых проблем и исключений процесса CLI
- Отслеживание содержимого рассуждений:захват процесса рассуждений модели (поле reasoning)
- Обработка различных типов сообщений:поддержка сообщений assistant, tool.started, tool.completed и т.д.
- Переключение режима разрешений:операции редактирования автоматически используют bypassPermissions, обычные запросы используют default
3. CopilotOptions: гибкая система конфигурации
Класс конфигурации поддерживает богатые настройки параметров:
public class CopilotOptions{ /// <summary> /// Указывает используемую модель, например "gpt-4", "gpt-5", "claude-opus-4.5" /// </summary> public string Model { get; set; } = "gpt-4";
/// <summary> /// Путь к исполняемому файлу Copilot CLI /// </summary> public string ExecutablePath { get; set; } = "copilot";
/// <summary> /// Время ожидания сессии /// </summary> public TimeSpan Timeout { get; set; } = TimeSpan.FromSeconds(1800);
/// <summary> /// Способ аутентификации /// </summary> public CopilotAuthSource AuthSource { get; set; } = CopilotAuthSource.LoggedInUser;
/// <summary> /// Режим разрешений /// </summary> public CopilotPermissionMode PermissionMode { get; set; } = CopilotPermissionMode.Default;
/// <summary> /// Идентификатор сессии для сохранения контекста /// </summary> public string? SessionId { get; set; }
/// <summary> /// Конфигурация разрешений инструментов /// </summary> public CopilotToolPermissions? Permissions { get; set; }}Конфигурация — это то, что должно быть просто достаточным. В конце концов, кто хочет писать кучу конфигураций, которые никогда не будут использоваться? Достаточно покрыть большинство сценариев.
Руководство по конфигурации
1. Базовая конфигурация
Добавьте конфигурацию поставщика Copilot в appsettings.json:
{ "AI": { "Providers": { "Providers": { "GitHubCopilot": { "Enabled": true, "ExecutablePath": "copilot", "Model": "gpt-5", "Timeout": 1800, "IdleTimeout": 300, "UseLoggedInUser": true, "NoAskUser": true, "PermissionMode": "default", "Permissions": { "AllowAllTools": false, "AllowAllPaths": false, "AllowedTools": ["Read", "Bash(git:*)", "Bash(cat:*)"], "DeniedTools": [] } } } } }}2. Выбор модели
Система поддерживает следующие модели (указывается через параметр --model Copilot CLI):
| Модель | Описание | Рекомендуемые сценарии |
|---|---|---|
| gpt-4 / gpt-4-turbo | Модели четвёртого поколения от OpenAI | Универсальные задачи, хорошее соотношение цены и качества |
| gpt-5 | Новейшая модель пятого поколения от OpenAI | Сложные рассуждения, требующие лучших результатов |
| claude-sonnet-4.5 | Anthropic Sonnet 4.5 | Баланс производительности и стоимости |
| claude-opus-4.5 | Anthropic Opus 4.5 | Высокоточные задачи |
В практике HagiCode мы по умолчанию используем GPT-4 в качестве повседневной модели, для сложных задач (например, крупный рефакторинг) переключаемся на GPT-5, а модели Claude предоставляем как альтернативу для пользователей, предпочитающих Anthropic.
3. Регистрация сервисов
Зарегистрируйте соответствующие сервисы в DI-контейнере:
// Регистрация поставщика Copilot AIservices.AddSingleton<IAIProvider, CopilotAIProvider>();
// Регистрация Orleans Grainservices.AddSingleton<IGitHubCopilotGrain, GitHubCopilotGrain>();
// Регистрация исполнителя процессовservices.AddSingleton<ICopilotProcessExecutor, CopilotProcessExecutor>();На самом деле это всего несколько строк кода, ничего особенного. Просто нужно зарегистрировать всё, что нужно, чтобы потом при использовании не возникло проблем с поиском.
Практические примеры
1. Базовый вызов
// Получаем Grainvar grain = grainFactory.GetGrain<IGitHubCopilotGrain>("session-123");
// Выполняем командуawait foreach (var response in grain.ExecuteCommandStreamAsync( "Проанализируй структуру кода в текущем каталоге и сгенерируй документацию", heroId: null, token: cancellationToken)){ switch (response.Type) { case ExecutorResponseType.Text: Console.Write(response.Content); break; case ExecutorResponseType.ToolCall: Console.WriteLine($"[Вызов инструмента] {response.ToolName}"); break; case ExecutorResponseType.Completion: Console.WriteLine($"\n[Завершено] Использование токенов: {response.PromptTokens}+{response.CompletionTokens}"); break; }}2. Сессия с контекстом
var requestSettings = new Dictionary<string, string>{ { "model", "gpt-5" }, { "temperature", "0.7" }, { "maxTokens", "4096" }, { "copilotSessionId", "existing-session-123" } // Сохраняем контекст сессии};
await foreach (var response in grain.ExecuteCommandStreamAsync( "На основе предыдущего анализа сгенерируй соответствующие модульные тесты", requestSettings: requestSettings, token: cancellationToken)){ // Обрабатываем ответ}3. Вызов в режиме редактирования
await foreach (var response in grain.RunEditAsync( "Преобразуй все имена PascalCase в camelCase", heroId: "hero-001", token: cancellationToken)){ if (response.Type == ExecutorResponseType.FileEdit) { Console.WriteLine($"[Редактирование] {response.FilePath}: {response.EditCount} изменений"); }}Лучшие практики
Сохранение сессии
Использование параметра copilotSessionId позволяет сохранять контекст между запросами, что очень полезно в сценариях с многоэтапными диалогами. Например:
// Первый этап: создаём контекстvar settings1 = new Dictionary<string, string> { { "copilotSessionId", "session-001" } };await grain.ExecuteCommandStreamAsync("Это проект на C#, использующий .NET 8", requestSettings: settings1);
// Второй этап: задаём вопрос на основе контекстаvar settings2 = new Dictionary<string, string> { { "copilotSessionId", "session-001" } };await grain.ExecuteCommandStreamAsync("Рекомендуй подходящую структуру проекта", requestSettings: settings2);В конце концов, ИИ не всемогущ — без контекста как он узнает, о чём вы говорите? Как в разговоре — нужно иметь обмен репликами, чтобы общение продолжалось.
Контроль разрешений
Выберите подходящий режим разрешений в зависимости от типа операции:
- Операции запроса:используйте режим
default, чтобы ИИ мог только читать файлы и выполнять безопасные Git-команды - Операции редактирования:используйте режим
bypassPermissions, чтобы позволить ИИ изменять файлы
var permissionMode = operationType == AIOperationType.Edit ? CopilotPermissionMode.BypassPermissions : CopilotPermissionMode.Default;Белый список инструментов
Через конфигурацию AllowedTools управляйте операциями, доступными ИИ:
{ "Permissions": { "AllowAllTools": false, "AllowedTools": [ "Read", "Bash(git:*)", "Bash(cat:*)", "Glob" ] }}В HagiCode мы строго ограничили права операций ИИ, разрешая только чтение файлов и выполнение Git-команд, обеспечивая безопасность системы.
В конце концов, безопасность — это то, с чем нельзя быть слишком осторожным. Кто знает, не решит ли ИИ по прихоти удалить весь ваш проект?
Обработка тайм-аутов
Тайм-аут по умолчанию установлен на 30 минут. Для операций, включающих большое количество файлов (например, полный анализ кода), может потребоваться корректировка:
var options = new CopilotOptions{ Timeout = TimeSpan.FromMinutes(60) // Расширяем до 60 минут};Часто задаваемые вопросы
Q:Как переключаться между различными ИИ-моделями?
A:Укажите через элемент конфигурации Model или requestSettings:
var settings = new Dictionary<string, string> { { "model", "claude-opus-4.5" } };На самом деле это просто изменение параметра, ничего сложного.
Q:Как долго сохраняется контекст сессии?
A:Зависит от реализации Copilot CLI, обычно очищается после тайм-аута простоя сессии (по умолчанию 5 минут). Можно настроить через конфигурацию IdleTimeout.
Q:Как обрабатывать падения процесса CLI?
A:CopilotAIProvider имеет встроенный механизм автоматического повтора, перехватывает исключения процесса и перезапускает CLI. Если количество последовательных сбоев слишком велико, выбрасывается AIProviderException.
Падения программ — это то, чего никто не может избежать. Можно только максимально повысить отказоустойчивость, а если действительно упадёт — перезапустить.
Q:Поддерживаются ли пользовательские инструменты?
A:Инструменты, поддерживаемые Copilot CLI, предопределены, но можно контролировать, какие инструменты доступны, через конфигурацию AllowedTools. Пользовательские инструменты требуют ожидания последующих обновлений Copilot CLI.
Заключение
Через унифицированную интеграцию с различными ИИ-моделями через Copilot CLI мы решили проблему поддержки множественных моделей в разработке HagiCode. Ключевые преимущества этого решения:
- Единый интерфейс:один код поддерживает различные модели, такие как GPT, Claude
- Управление сессиями:автоматическая обработка сохранения контекста и изоляции сессий
- Интеграция инструментов:встроенные операции с файлами, Git-операции и другие часто используемые инструменты
- Потоковые ответы:возврат вывода ИИ в реальном времени, улучшение пользовательского опыта
- Безопасность и контроль:детектирующий контроль разрешений и белый список инструментов
Если ваш проект также требует поддержки различных ИИ-моделей или вы ищете зрелое решение интеграции CLI-инструментов, попробуйте Copilot CLI. Эта архитектура была полностью проверена в HagiCode и может поддерживать сложные требования производственной среды.
В конце концов, кто хочет писать код вызова для каждой модели? При наличии единого унифицированного решения всем будет спокойнее.
Справочные материалы
- Официальная документация GitHub Copilot CLI
- Распределённый фреймворк Orleans
- Адрес проекта HagiCode
- Официальный сайт HagiCode
- Руководство по установке HagiCode
- Быстрая установка HagiCode Desktop
Если эта статья вам помогла:
- Поставьте звёздочку на GitHub: github.com/HagiCode-org/site
- Посетите официальный сайт для получения дополнительной информации: hagicode.com
- Посмотрите демонстрационное видео официальной версии: www.bilibili.com/video/BV1z4oWB3EpY/
- Установка в один клик: docs.hagicode.com/installation/docker-compose
- Быстрая установка для desktop: hagicode.com/desktop/
- Открытое бета-тестирование началось, добро пожаловать на установку и испытание
开始使用 HagiCode
一次安装,几分钟上手
HagiCode for Windows 在 Microsoft Store 免费提供。打开商店即可安装并保持更新;也可以先对比各版本与定价,再决定从哪个渠道开始。