Перейти к содержимому

Как унифицированно интегрировать GPT, Claude и другие ИИ-модели с помощью Copilot CLI

HagiCode for Windows Microsoft Store artwork
HagiCode for Windows is now on Microsoft Store
HagiCode for Windows is officially live on Microsoft Store. Windows users can install it directly from the storefront and stay on the store-managed update path. Open the listing and take a look.
Open Microsoft Store

Как унифицированно интегрировать 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.5Anthropic Sonnet 4.5Баланс производительности и стоимости
claude-opus-4.5Anthropic Opus 4.5Высокоточные задачи

В практике HagiCode мы по умолчанию используем GPT-4 в качестве повседневной модели, для сложных задач (например, крупный рефакторинг) переключаемся на GPT-5, а модели Claude предоставляем как альтернативу для пользователей, предпочитающих Anthropic.

3. Регистрация сервисов

Зарегистрируйте соответствующие сервисы в DI-контейнере:

// Регистрация поставщика Copilot AI
services.AddSingleton<IAIProvider, CopilotAIProvider>();
// Регистрация Orleans Grain
services.AddSingleton<IGitHubCopilotGrain, GitHubCopilotGrain>();
// Регистрация исполнителя процессов
services.AddSingleton<ICopilotProcessExecutor, CopilotProcessExecutor>();

На самом деле это всего несколько строк кода, ничего особенного. Просто нужно зарегистрировать всё, что нужно, чтобы потом при использовании не возникло проблем с поиском.

Практические примеры

1. Базовый вызов

// Получаем Grain
var 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. Ключевые преимущества этого решения:

  1. Единый интерфейс:один код поддерживает различные модели, такие как GPT, Claude
  2. Управление сессиями:автоматическая обработка сохранения контекста и изоляции сессий
  3. Интеграция инструментов:встроенные операции с файлами, Git-операции и другие часто используемые инструменты
  4. Потоковые ответы:возврат вывода ИИ в реальном времени, улучшение пользовательского опыта
  5. Безопасность и контроль:детектирующий контроль разрешений и белый список инструментов

Если ваш проект также требует поддержки различных ИИ-моделей или вы ищете зрелое решение интеграции CLI-инструментов, попробуйте Copilot CLI. Эта архитектура была полностью проверена в HagiCode и может поддерживать сложные требования производственной среды.

В конце концов, кто хочет писать код вызова для каждой модели? При наличии единого унифицированного решения всем будет спокойнее.

Справочные материалы

Если эта статья вам помогла:

开始使用 HagiCode

一次安装,几分钟上手

HagiCode for Windows 在 Microsoft Store 免费提供。打开商店即可安装并保持更新;也可以先对比各版本与定价,再决定从哪个渠道开始。