Skip to content

Latest commit

 

History

History
880 lines (680 loc) · 46.7 KB

File metadata and controls

880 lines (680 loc) · 46.7 KB
Delibera

Delibera

⚖️ Продуманные решения с помощью ИИ

Коллективное принятие решений через структурированное обсуждение ИИ — с RAG, pgvector, Knowledge Keeper, 🛠️ Operator (MCP-инструменты), Chairman, 🔥 сжатием контекста, ✂️ AutoChunking, 💉 Dependency Injection и 📋 журналированием выполнения

NuGet License: MIT .NET 10 C# 15

🇬🇧 English version (README.md)


📖 Обзор

Delibera — это фреймворк на C# / .NET 10, который оркеструет многомодельные обсуждения между LLM. Несколько моделей ИИ рассуждают над вопросом в течение структурированных раундов, критикуют ответы друг друга, а Chairman (председатель) взвешивает аргументы, чтобы синтезировать сбалансированный финальный вердикт — обогащённый Knowledge Keeper на базе Qdrant или PostgreSQL/pgvector (RAG), с интеллектуальным сжатием контекста для минимизации расхода токенов.

Название происходит от слова deliberation — тщательного взвешивания доказательств и точек зрения перед принятием решения. Delibera привносит эту дисциплину в ИИ, помогая командам приходить к продуманным, хорошо обоснованным результатам, а не к догадкам одной модели.


✨ Ключевые возможности

Возможность Описание
🏛️ Многомодельные советы Оркестрация любого числа LLM-участников по структурированным раундам дебатов
⚖️ Синтез Chairman Выделенный модератор открывает, регулирует и синтезирует финальный вердикт
📚 Knowledge Keeper (RAG) Семантический поиск по раундам со структурированными ответами и цитированием
🛠️ Operator (MCP-инструменты) Микроагент, делегирующий задачи MCP-серверам (веб, файлы, Marp, Notion, …) по запросу в ходе дебатов
🐘 Qdrant + pgvector Подключаемые векторные хранилища — отдельная БД или ваш существующий PostgreSQL
🗜️ Сжатие контекста 4 стратегии (Semantic, Deduplication, Summarization, Hybrid) экономят 30–70% токенов
✂️ AutoChunking Прогрессивное раскрытие больших документов по раундам — с учётом контекстных окон моделей
💉 Dependency Injection Расширение AddDelibera() для IServiceCollection с полной привязкой опций
📋 Журналирование выполнения Модель ExecutionLog с LogLevel — события Chairman, KK, сжатия и участников
📁 Раздельный вывод файлов Экспорт result.md, statistics.md и logs.md по отдельности
🔌 Interface-First Чистые абстракции для провайдеров, фабрик, билдеров и исполнителей
🤝 Microsoft.Extensions.AI Поддержка IChatClient / IEmbeddingGenerator — подключайте OpenAI, Azure OpenAI, Ollama и любые совместимые бэкенды, с middleware (function calling, логирование)
🧱 Современный C# 15 (preview) Построено на .NET 10 с LangVersion=preview, file-scoped namespaces, records, span/SIMD горячие пути

🆕 Что нового в v10.2.6

Возможность Описание
🌊 Асинхронный потоковый совет ICouncilExecutor.StreamDebateAsync отдаёт каждый DebateRound по мере завершения через внутренний мост Channel<DebateRound> — идеально для ASP.NET Core SSE, WebSocket, Blazor и CLI в реальном времени. Включены метаданные DebateRound.Total + IsFinal + LastStreamedResult.
🗳️ Подключаемый движок голосования IVotingStrategy со встроенными MajorityVotingStrategy, BordaCountVotingStrategy, WeightedVotingStrategy (повеса по участникам MemberWeights). Chairman.CreateVoting(...) подменяет синтез Chairman на верифицируемый подсчёт, который отображается как секция 🗳️ Voting Tally в Markdown-выводе.
💾 Персистентность и возобновление дебатов IDebateStore + FileDebateStore (атомарная запись JSON с rename, RetentionDays) + InMemoryDebateStore. CouncilBuilder.WithPersistence(...) сохраняет чекпоинт после каждого раунда; ResumeFrom(debateId) продолжает с последнего завершённого раунда после сбоя или паузы.
🧠 Память агентов IAgentMemory с реализациями InMemoryAgentMemory (схожесть Жаккара), QdrantAgentMemory (отдельная коллекция на агента), PgVectorAgentMemory (общая таблица с фильтром agent_name). CouncilBuilder.WithAgentMemory(...) подгружает контекст до и сохраняет выводы после каждого совета.
📊 OpenTelemetry-стиль наблюдаемости DeliberaActivitySource + DeliberaMeter с гистограммами, счётчиками и gauge для спанов delibera.council.execute, delibera.council.round, delibera.compression и т.д. Нулевые накладные расходы, когда слушатель не подключён. Включается через CouncilBuilder.WithTelemetry(...).
📋 Структурированный вывод IStructuredOutputSerializer + JsonSchemaOutputSerializer (использует .NET 10 JsonSchemaExporter). ICouncilExecutor.ExecuteTypedAsync<TVerdict> возвращает строго типизированный вердикт, десериализованный из ответа Chairman. Одна автоматическая повторная попытка при ошибке десериализации.
🔄 Адаптивная смена стратегии IStrategySelector + AdaptiveStrategySelector меняют стратегию дебатов на лету при стагнации ответов (StagnationThreshold подряд идущих раундов с низким разнообразием, fallback на Левенштейна при отсутствии embedding-провайдера).
📋 Шаблоны дебатов 6 встроенных шаблонов (DebateTemplate.ArchitectureReview, RiskAssessment, CodeReview, ProductDecision, SecurityAudit, DataArchitecture) с преднастроенными участниками, персонами, стратегиями и Chairman.
⚡ Quick Wins DebateResult.ToHtml() + SaveToHtmlAsync(); CouncilBuilder.WithTimeout(TimeSpan); пресеты Persona; CouncilBenchmark для сравнения моделей; WithParticipantLimit(int) как защитный гард.

Полные release notes v10.2.6 смотрите в CHANGELOG.md, оригинальный roadmap — в docs/v10.2.6.md.


📑 Содержание


🚀 Быстрый старт

Требования и модели

  • .NET 10 SDK (≥ 10.0.301) — проект нацелен на net10.0 и собирается с LangVersion=preview для включения возможностей C# 15. См. docs/NET10-Upgrade-RU.md для полных заметок о миграции.
  • Запущенный экземпляр Ollama — локально (ollama serve) или Ollama Cloud (только API-ключ, без установки).
  • Минимальный набор моделей, перечисленный ниже.
  • Опционально — для роли Operator: Node.js + npx для запуска MCP-серверов (например, @playwright/mcp, @marp-team/marp-cli). См. Operator (MCP-инструменты).

🟢 Минимальный — для небольших дебатов (≈ 2 ГБ всего)

Подходит для smoke-тестов, слабого железа и быстрых запусков из CLI.

Назначение Модель Размер Команда загрузки
Участник совета llama3.2:1b 1.3 ГБ ollama pull llama3.2:1b
Участник совета qwen2.5:1.5b 1.1 ГБ ollama pull qwen2.5:1.5b
Эмбеддинги (RAG) nomic-embed-text 274 МБ ollama pull nomic-embed-text

🟡 Стандартный — рекомендуется для большинства случаев (≈ 7 ГБ всего)

Хорошее качество рассуждений при низкой задержке. Это набор по умолчанию, используемый по всему README.

Назначение Модель Размер Команда загрузки
Участник совета llama3.2:3b 2.0 ГБ ollama pull llama3.2:3b
Участник совета qwen2.5:7b 4.7 ГБ ollama pull qwen2.5:7b
Эмбеддинги (RAG) nomic-embed-text 274 МБ ollama pull nomic-embed-text

🔴 Высокопроизводительный — для продакшн-уровня дебатов (≈ 30+ ГБ)

Более тяжёлые локальные модели, рекомендуются на GPU с ≥ 24 ГБ VRAM или на Ollama Cloud.

Назначение Модель Размер Команда загрузки
Участник совета llama3.1:8b 4.9 ГБ ollama pull llama3.1:8b
Участник совета qwen2.5:14b 9.0 ГБ ollama pull qwen2.5:14b
Участник совета mistral:7b 4.4 ГБ ollama pull mistral:7b
Chairman qwen2.5:14b (или больше) 9.0 ГБ ollama pull qwen2.5:14b
Эмбеддинги (RAG) nomic-embed-text 274 МБ ollama pull nomic-embed-text

💡 Ollama Cloud использует те же имена моделей, но не требует места на локальном диске — нужен только API-ключ. См. раздел конфигурации для его настройки.

Установка

dotnet add package Delibera.Core

Минимальный пример

using Delibera.Core.Council;
using Delibera.Core.Providers;

using var factory = new ProviderFactory();
var ollama = factory.CreateOllama("http://localhost:11434");

var result = await new CouncilBuilder()
    .AddMember("llama3.2:3b", ollama, "Analyst")
    .AddMember("qwen2.5:7b", ollama, "Strategist")
    .SetChairman(Chairman.CreateStandard("qwen2.5:7b", ollama))
    .WithStandardDebate()
    .WithSystemPrompt("You are a software architecture expert.")
    .WithUserPrompt("Microservices vs Monolith for a 5-person startup?")
    .WithMaxRounds(4)
    .SaveResultTo("./deliberation.md")
    .Build()
    .ExecuteAsync();

Console.WriteLine(result.FinalVerdict);

📄 См. docs/QuickStart-RU.md для пошагового руководства.

Запуск

dotnet run

Delibera проведёт структурированные многораундовые дебаты и запишет полную стенограмму и вердикт председателя в файл deliberation.md.


💉 Dependency Injection

Зарегистрируйте все сервисы Delibera одной строкой:

using Delibera.Core.DependencyInjection;

// Вариант A: С привязкой конфигурации (привязывает секцию "Delibera")
services.AddDelibera(configuration, "Delibera");

// Вариант B: С делегатом опций
services.AddDelibera(options =>
{
    options.Strategy = "Standard";
    options.MaxRounds = 4;
    options.Temperature = 0.7f;
    options.Compression.Enabled = true;
    options.Compression.Strategy = "Hybrid";
    options.Compression.TargetRatio = 0.5;
});

// Вариант C: Только значения по умолчанию
services.AddDelibera();

Резолвит из DI следующие интерфейсы:

Интерфейс Реализация Время жизни
ILLMProviderFactory ProviderFactory Singleton
IRagProviderFactory RagProviderFactory Singleton
ICompressionFactory CompressionService Singleton
ICouncilBuilder CouncilBuilder Transient

Конфигурация (appsettings.json)

{
  "Delibera": {
    "Strategy": "Standard",
    "MaxRounds": 4,
    "Temperature": 0.7,
    "SystemPrompt": "You are a knowledgeable AI expert participating in a council debate.",
    "Providers": {
      "DefaultType": "Ollama",
      "DefaultEndpoint": "http://localhost:11434",
      "ApiKey": "",
      "EmbeddingModel": "nomic-embed-text"
    },
    "Compression": {
      "Enabled": true,
      "Strategy": "Hybrid",
      "TargetRatio": 0.5,
      "EnableCache": true,
      "MaxCacheEntries": 256
    },
    "Rag": {
      "Enabled": false,
      "ProviderType": "Qdrant",
      "Host": "localhost",
      "Port": 6334,
      "CollectionName": "council_knowledge",
      "ConnectionString": null
    },
    "Output": {
      "Directory": "./debate_results",
      "SeparateFiles": true,
      "FilePrefix": null
    }
  }
}

Чтобы использовать Ollama Cloud, задайте Providers:DefaultEndpoint равным https://api.ollama.com и поместите ключ в Providers:ApiKey (или OllamaCloud:ApiKey в секции DeliberaApp, используемой консольным приложением — см. Примеры ConsoleApp).


🛠️ Operator (MCP-инструменты)

Operator — это лёгкий микроагент, который соединяет совет с внешним миром через серверы MCP (Model Context Protocol). Он предоставляет участникам дебатов любые инструменты, которые дают эти серверы — веб-навигацию, доступ к файловой системе, генерацию Marp-презентаций, Notion, PostgreSQL и т. д.

Как это работает

  1. Operator подключается к одному или нескольким MCP-серверам и обнаруживает их инструменты при InitializeAsync.

  2. Участникам сообщается (в их системном промпте), что умеет Operator, и они могут делегировать задачу в любой момент дебатов, написав маркер в своём сообщении:

    [[OPERATOR: открой https://modelcontextprotocol.io и кратко перескажи, что такое MCP]]
    
  3. Operator интерпретирует запрос своей собственной (более дешёвой) LLM-моделью, выбирает и вызывает нужные MCP-инструменты, интерпретирует результаты и возвращает краткий ответ, который внедряется в следующий раунд.

  4. Если совет использует сжатие контекста, Operator может переиспользовать ту же стратегию для сжатия больших выводов инструментов перед их возвратом в дебаты. Его DisposeAsync — это ValueTask (паттерн IAsyncDisposable из .NET 10), поэтому MCP-клиенты освобождаются без аллокации Task.

Все взаимодействия с Operator записываются по раундам и отображаются в финальном Markdown-отчёте в блоке 🛠️ Operator Interactions.

Настройка MCP-серверов

using Delibera.Core.Models;

var servers = new[]
{
    // stdio-транспорт — запускает локальный процесс MCP-сервера
    McpServerConfig.Stdio(
        name: "browser",
        command: "npx",
        arguments: new[] { "-y", "@playwright/mcp@latest", "--headless" }),

    McpServerConfig.Stdio(
        name: "marp",
        command: "npx",
        arguments: new[] { "-y", "@marp-team/marp-cli", "--server", "./out" }),

    // …или HTTP/SSE-транспорт для удалённого MCP-сервера
    // McpServerConfig.Http(
    //     name: "remote",
    //     endpoint: "https://my-mcp-host.example.com/mcp",
    //     additionalHeaders: new Dictionary<string, string> { ["Authorization"] = "Bearer <token>" }),
};
Сервер Транспорт Команда запуска Что даёт
🌐 browser stdio npx -y @playwright/mcp@latest --headless Навигация по сайтам, чтение страниц, клики, скриншоты
🎯 marp stdio npx -y @marp-team/marp-cli --server <dir> Генерация презентаций (HTML/PDF/PPTX) из Markdown

Быстрое использование (внутри совета)

using Delibera.Core.Council;
using Delibera.Core.Providers.LLM;

var ollama = new OllamaProvider("http://localhost:11434");

var council = new CouncilBuilder()
    .AddMember("llama3.2:3b", ollama, "Optimist")
    .AddMember("qwen2.5:7b",  ollama, "Skeptic")
    .SetChairman(Chairman.CreateStandard("qwen2.5:7b", ollama))
    // Operator использует свою более дешёвую модель; reuseCompression разделяет компрессор совета
    .WithOperator("llama3.2:3b", ollama, servers, reuseCompression: true)
    .WithStandardDebate()
    .WithUserPrompt("Research the latest .NET 10 features and prepare a short summary.")
    .WithMaxRounds(4)
    .Build()
    .ExecuteAsync();

Предпочитаете создать Operator самостоятельно? Передайте готовый экземпляр:

using Delibera.Core.Council;
using Delibera.Core.Interfaces;
using Delibera.Core.Models;
using Delibera.Core.Providers.Mcp;

var @operator = new Operator(
    new CouncilMember("llama3.2:3b", ollama, "Operator"),
    new IMcpClient[] { new McpClientAdapter(servers[0]), new McpClientAdapter(servers[1]) },
    compressor: null,            // необязательный IContextCompressor
    compressionOptions: null);   // необязательные CompressionOptions

var council = new CouncilBuilder()
    /* …участники… */
    .WithOperator(@operator)
    .Build();

Прямое использование (без совета)

await using var @operator = new Operator(
    new CouncilMember("llama3.2:3b", ollama, "Operator"),
    new IMcpClient[] { new McpClientAdapter(servers[0]), new McpClientAdapter(servers[1]) });

await @operator.InitializeAsync();

var result = await @operator.ExecuteTaskAsync(
    "Open https://modelcontextprotocol.io and briefly summarize what MCP is.");

Console.WriteLine(result.FinalAnswer);

Dependency Injection

Настройте Operator декларативно в appsettings.json в секции Delibera:Operator:

{
  "Delibera": {
    "Operator": {
      "Enabled": true,
      "ModelName": "llama3.2:3b",
      "ReuseCompression": true,
      "McpServers": [
        {
          "Name": "browser",
          "Transport": "Stdio",
          "Command": "npx",
          "Arguments": [ "-y", "@playwright/mcp@latest", "--headless" ]
        },
        {
          "Name": "remote",
          "Transport": "Http",
          "Endpoint": "https://my-mcp-host.example.com/mcp",
          "AdditionalHeaders": { "Authorization": "Bearer <token>" }
        }
      ]
    }
  }
}

▶️ Полный рабочий пример находится в OperatorMcpToolsExample.cs. Запустите его командой dotnet run --project src/Delibera.ConsoleApp -- --operator-mcp. Полное техническое описание см. в docs/NET10-Upgrade-RU.md.


🗜️ Сжатие контекста

Автоматически сжимайте контекст между раундами обсуждения — экономьте 30–70% токенов без потери смысла.

Стратегия Как работает Лучше всего для
Semantic Эмбеддинг предложений, ранжирование по релевантности, топ-N Большие контексты знаний
Deduplication Удаляет семантически похожие предложения между участниками Многомодельные дебаты с пересечениями
Summarization LLM создаёт краткое резюме, сохраняя ключевые факты Максимальная степень сжатия
Hybrid Конвейер Dedup → Semantic → Summarize Лучшее общее качество
None Без изменений (когда отключено) Отладка
using Delibera.Core.Compression;
using Delibera.Core.Providers.LLM;

var ollama = new OllamaProvider("http://localhost:11434");
var embeddings = new OllamaEmbeddingProvider(ollama, "nomic-embed-text");

var result = await new CouncilBuilder()
    .AddMember("llama3.2:3b", ollama, "Analyst")
    .AddMember("qwen2.5:7b", ollama, "Strategist")
    .SetChairman(Chairman.CreateStandard("qwen2.5:7b", ollama))
    .WithCompression(CompressionStrategy.Hybrid,
        llmProvider: ollama,
        modelName: "llama3.2:3b",
        embeddingProvider: embeddings)
    .WithCompressionOptions(new CompressionOptions { TargetRatio = 0.5 })
    .WithCompressionCache()
    .WithUserPrompt("Analyze our architecture options...")
    .WithMaxRounds(4)
    .Build()
    .ExecuteAsync();

Console.WriteLine(result.TokenStats?.ToSummary());

Конвейер сжатия

IContextCompressor
├── SemanticCompressor        ← Ранжирование предложений на основе эмбеддингов
├── DeduplicationCompressor   ← Удаление дубликатов по схожести
├── SummarizationCompressor   ← Резюмирование с помощью LLM
├── HybridCompressor          ← Многоэтапный конвейер (Dedup → Semantic → Summarize)
└── PassThroughCompressor     ← Без операций (когда отключено)

CompressionFactory            ← Статическая фабрика (Create по enum или строке)
CompressionService            ← DI-дружественная обёртка над CompressionFactory
CompressionCache              ← LRU-кэш с ключами SHA-256
TokenCounter                  ← Эвристическая оценка токенов

✂️ AutoChunking

Автоматическое разбиение больших документов (договоры, отчёты, статьи) на чанки, соответствующие размеру контекстного окна моделей, с распределением по раундам дебатов через прогрессивное раскрытие (progressive disclosure). Если документ превышает контекстное окно самой маленькой модели, оркестратор создаёт план чанкинга и равномерно распределяет чанки — каждая модель получает полное представление к финальному раунду.

Как это работает

  1. Определение моделей — запрос контекстного окна каждой модели через GetModelCapabilitiesAsync() (Ollama /api/show или встроенный реестр из 40+ моделей).
  2. Расчёт накладных расходов — системный промпт + вопрос + буфер ответа + история.
  3. План чанкинга — разбивка документа по семантическим границам (Markdown-заголовки → параграфы → предложения), каждый чанк ≤ minWindow − overhead − safetyMargin.
  4. Прогрессивное раскрытие — Раунд 1 получает чанки 1..N/3, Раунд 2 — N/3+1..2N/3 и т.д. Каждый раунд видит маркеры [Chunk X/Y] SectionTitle + сводку предыдущих раундов.

Три способа конфигурации

// Способ 1: Fluent API
var executor = new CouncilBuilder()
    .WithAutoChunking(new AutoChunkingOptions
    {
        Strategy = ChunkingStrategy.SemanticBoundary,
        SafetyMargin = 0.15,
        MaxChunksPerRound = 3
    })
    /* …участники, chairman, знания… */
    .Build();

// Способ 2: Объект CouncilOptions (из DI или вручную)
var options = new CouncilOptions
{
    AutoChunking = new AutoChunkingConfig { Enabled = true, Strategy = "SemanticBoundary" }
};
var executor = new CouncilBuilder(options)  // или .WithOptions(options)
    /* … */
    .Build();

// Способ 3: Лямбда-конфигурация
var executor = new CouncilBuilder()
    .WithOptions(o =>
    {
        o.AutoChunking.Enabled = true;
        o.AutoChunking.MaxChunksPerRound = 2;
    })
    /* … */
    .Build();

Конфигурация (appsettings.json)

{
  "Delibera": {
    "AutoChunking": {
      "Enabled": true,
      "Strategy": "SemanticBoundary",
      "SafetyMargin": 0.15,
      "MaxChunksPerRound": 3,
      "EnableMapReduce": true,
      "EnableProgressiveDisclosure": true,
      "ModelContextWindows": {
        "my-custom-model": 65536
      }
    }
  }
}

Реестр контекстных окон моделей

// Запрос известных моделей
var window = ModelContextWindowRegistry.GetContextWindow("llama3.2"); // → 131072
var window = ModelContextWindowRegistry.GetContextWindow("phi3:mini"); // → 4096

// Регистрация своих моделей
ModelContextWindowRegistry.Register("my-fine-tuned-model", 65536);

▶️ Запустите демо: dotnet run --project src/Delibera.ConsoleApp -- --autochunking


📚 Интеграция RAG

Используйте выделенный экземпляр Qdrant или вашу существующую базу PostgreSQL/pgvector в качестве векторного хранилища.

using Delibera.Core.Council;
using Delibera.Core.Models;
using Delibera.Core.Providers.LLM;
using Delibera.Core.Providers.RAG;

var ollama = new OllamaProvider("http://localhost:11434");
var embeddings = new OllamaEmbeddingProvider(ollama, "nomic-embed-text");

// pgvector — просто добавьте строку подключения
var ragFactory = new RagProviderFactory();
var rag = ragFactory.CreatePgVector(
    embeddings,
    "Host=localhost;Database=council_vectors;Username=postgres;Password=postgres");

await rag.IndexDocumentAsync("my_collection", documentText);
var results = await rag.SearchAsync("my_collection", "query", limit: 5);

// Подключаем к Knowledge Keeper
var kkMember = new CouncilMember("llama3.2:3b", ollama, "Knowledge Keeper");
var keeper = new KnowledgeKeeper(rag, kkMember, "my_knowledge");
await keeper.IndexFileAsync("./docs/architecture.md");
IRagProvider
├── QdrantRagProvider
│   └── QdrantVectorStore     ← Qdrant gRPC
└── PgVectorRagProvider
    └── PgVectorStore         ← PostgreSQL/pgvector

IEmbeddingProvider
└── OllamaEmbeddingProvider

Затем Knowledge Keeper присоединяется к совету через WithKnowledgeKeeper(...) — см. пример RAG для полного рабочего демо.


🗣️ Стратегии дебатов

Стратегия Поток Сценарий использования
StandardDebate Initial → Critique → Improved → Verdict Общий анализ
CritiqueDebate Position → Attack → Defence → Judge Проверка гипотез
ConsensusDebate Perspectives → Common Ground → Consensus → Facilitator Поиск оптимального решения

Каждая стратегия реализована как IDebateStrategy — см. src/Delibera.Core/Debate/ для полного исходного кода.

Паттерны проектирования

Паттерн Использование
Factory ProviderFactory, RagProviderFactory, CompressionFactory, Chairman
Strategy IDebateStrategy, IContextCompressor
Builder Fluent API CouncilBuilder
Template Method Абстрактный базовый класс DebateScenario
Cache CompressionCache с ключами SHA-256
Observer Событие OnRoundCompleted у CouncilExecutor

📁 Структура выходных файлов

Каждое обсуждение можно экспортировать как один файл или как три отдельных Markdown-документа:

var result = await executor.ExecuteAsync();

// Сохранить в 3 отдельных файла
var (resultPath, statsPath, logsPath) = await result.SaveAllAsync("./output");
// Создаёт: debate_20260604_120000_result.md
//          debate_20260604_120000_statistics.md
//          debate_20260604_120000_logs.md

// Или сохранить по отдельности
await result.SaveToMarkdownAsync("result.md");
await result.SaveStatisticsAsync("statistics.md");
await result.SaveLogsAsync("logs.md");
Файл Содержимое
*_result.md Полная стенограмма обсуждения, раунды и финальный вердикт председателя
*_statistics.md Статистика использования токенов с разбивкой по раундам
*_logs.md Журналы выполнения (ExecutionLog) для Chairman, KK, сжатия и участников

💻 Примеры ConsoleApp

В репозитории есть Delibera.ConsoleApp — запускаемый демо-проект, который задействует каждую возможность. Запускайте его из корня репозитория:

# Клонировать репозиторий
git clone https://github.com/delibera/Delibera.git
cd Delibera/src/Delibera.ConsoleApp

# Запустить конкретный пример
dotnet run -- --di                 # Dependency Injection
dotnet run -- --separate-files     # Сохранить result.md, statistics.md, logs.md
dotnet run -- --compression        # Демо сжатия контекста
dotnet run -- --multiprovider      # Совет с несколькими провайдерами (cloud + local)
dotnet run -- --rag                # RAG на базе Qdrant с Knowledge Keeper
dotnet run -- --pgvector           # RAG на базе pgvector
dotnet run -- --operator           # Основы роли Operator (MCP-инструменты)
dotnet run -- --operator-mcp       # 🆕 Operator с MCP-серверами browser + Marp
dotnet run -- --autochunking       # 🆕 Демо AutoChunking (большие документы)

# Или запустить полное демо по умолчанию (читает appsettings.json)
dotnet run

Консольное приложение читает appsettings.json, который использует секцию DeliberaApp — по умолчанию она указывает на Ollama Cloud и показывает, как подключить несколько провайдеров, RAG и сжатие в одном месте.


🛠️ Установка и сборка

Клонирование и сборка

git clone https://github.com/delibera/Delibera.git
cd Delibera

# Собрать всё решение
dotnet build --configuration Release

# Запустить консольное демо
cd src/Delibera.ConsoleApp
dotnet run

Инфраструктура одной командой (Docker Compose)

Поднимите Qdrant + PostgreSQL/pgvector за один шаг. (Ollama намеренно не включена — установите её нативно, чтобы GPU-драйвер использовался напрямую.)

# Из корня репозитория
docker compose up -d

# В другом терминале запустите консольное приложение
cd src/Delibera.ConsoleApp
dotnet run

Compose-стек предоставляет:

Сервис URL Назначение
Qdrant (REST) http://localhost:6333 UI / REST векторного хранилища
Qdrant (gRPC) localhost:6334 gRPC-клиент (используется Delibera)
PostgreSQL localhost:5432 RAG-хранилище pgvector

Учётные данные по умолчанию: postgres / postgres, база council_vectors.

Если эти сервисы уже запущены нативно, просто пропустите docker compose и направьте консольное приложение на них — appsettings.json по умолчанию использует localhost.

Альтернатива вручную (по одному контейнеру)

# Запуск с Qdrant (Docker)
docker run -d -p 6333:6333 -p 6334:6334 qdrant/qdrant

# Запуск с pgvector (Docker)
docker run -d -p 5432:5432 -e POSTGRES_PASSWORD=postgres pgvector/pgvector:pg16

# Затем включите расширение pgvector
docker exec -it <container> psql -U postgres -d council_vectors -c "CREATE EXTENSION IF NOT EXISTS vector;"

NuGet-зависимости

Пакет Назначение
OllamaSharp Клиент API Ollama
Qdrant.Client gRPC-клиент векторной БД Qdrant
Npgsql ADO.NET-провайдер PostgreSQL
Pgvector Поддержка типов pgvector для Npgsql
ModelContextProtocol MCP-клиент для роли Operator
Microsoft.Extensions.AI Унифицированные AI-абстракции IChatClient / IEmbeddingGenerator и middleware
Microsoft.Extensions.* Конфигурация, DI и Options

🤝 Microsoft.Extensions.AI

Delibera интегрирована с Microsoft.Extensions.AI (v10.7.0) — стандартным слоем абстракций .NET для генеративного AI. Это позволяет запускать совет с любым бэкендом, реализующим IChatClient (OpenAI, Azure OpenAI, Ollama, Anthropic, LM Studio / LocalAI / vLLM, …) и собирать конвейер middleware (вызов функций/инструментов, логирование, кэширование, телеметрия) — без написания отдельного провайдера под каждого поставщика.

Что вы получаете

Тип Роль
ChatClientLLMProvider Адаптирует любой IChatClient к ILLMProvider Delibera (со стримингом через ChatStreamAsync)
EmbeddingGeneratorProvider Адаптирует любой IEmbeddingGenerator<string, Embedding<float>> к IEmbeddingProvider для RAG
MicrosoftAIExtensions Мосты: AsLLMProvider(), AsEmbeddingProvider(), AsChatClient(), WithMiddleware()
ProviderFactory.CreateFromChatClient(...) Создаёт кэшируемый провайдер прямо из IChatClient
AddDeliberaChatClient(...) / AddDeliberaEmbeddingGenerator(...) Регистрация стандартных AI-сервисов в DI

Использование любого IChatClient как провайдера Delibera

using Delibera.Core.Extensions;
using Microsoft.Extensions.AI;

// 1) Подключите свой IChatClient. Для OpenAI:
//    dotnet add package Microsoft.Extensions.AI.OpenAI
IChatClient client = new OpenAI.Chat.ChatClient("gpt-4o-mini", apiKey).AsIChatClient();

// 2) (опционально) middleware — вызов функций + логирование
client = client.WithMiddleware(enableFunctionInvocation: true, loggerFactory);

// 3) отдайте его Delibera
ILLMProvider provider = client.AsLLMProvider("OpenAI");

var executor = new CouncilBuilder()
   .AddMember("gpt-4o-mini", provider, "Архитектор")
   .AddMember("gpt-4o-mini", provider, "Скептик")
   .SetChairman(Chairman.CreateStandard("gpt-4o-mini", provider))
   .WithStandardDebate()
   .WithUserPrompt("Модульный монолит или микросервисы для команды из 5 человек?")
   .Build();

Ollama работает «из коробки», так как OllamaApiClient из OllamaSharp нативно реализует IChatClient и IEmbeddingGenerator:

using var ollama = new OllamaProvider("http://localhost:11434");
IChatClient chat = ollama.AsChatClient();                 // готов к middleware
ILLMProvider provider = chat.AsLLMProvider("Ollama");
IEmbeddingProvider embeddings = ollama.AsEmbeddingGenerator().AsEmbeddingProvider("nomic-embed-text");

Стриминг

await foreach (var chunk in provider.ChatStreamAsync("gpt-4o-mini", systemPrompt, userPrompt))
   Console.Write(chunk);

ChatStreamAsync — это additive-метод по умолчанию в ILLMProvider: провайдеры на базе IChatClient стримят токен за токеном, а старые провайдеры прозрачно используют один вызов.

Внедрение зависимостей (DI)

services.AddDeliberaChatClient(
   sp => new OpenAI.Chat.ChatClient("gpt-4o-mini", apiKey)
            .AsIChatClient()
            .WithMiddleware(enableFunctionInvocation: true),
   providerName: "OpenAI");

services.AddDeliberaEmbeddingGenerator(
   sp => /* ваш IEmbeddingGenerator */,
   modelName: "text-embedding-3-small");

Попробуйте: dotnet run --project src/Delibera.ConsoleApp -- --msai


🏛️ Архитектура

Delibera.Core
├── Council/              ← CouncilBuilder, CouncilExecutor, Chairman, KnowledgeKeeper, Operator
├── Debate/               ← StandardDebate, CritiqueDebate, ConsensusDebate
├── Compression/          ← Semantic / Deduplication / Summarization / Hybrid
├── Chunking/             ← AutoChunker, AutoChunkingOrchestrator, AutoChunkingOptions
├── Providers/
│   ├── LLM/              ← OllamaProvider, ChatClientLLMProvider, EmbeddingGeneratorProvider
│   ├── RAG/              ← QdrantRagProvider, PgVectorRagProvider
│   └── Mcp/              ← McpClientAdapter (Operator ↔ MCP-серверы)
├── Extensions/           ← MicrosoftAIExtensions (мосты IChatClient ↔ ILLMProvider)
├── DependencyInjection/  ← AddDelibera() / AddDeliberaChatClient() + CouncilOptions
├── Knowledge/            ← MarkdownKnowledgeBase
├── Models/               ← CouncilMember, DebateResult, DebateRound, TokenStatistics, ...
└── Interfaces/           ← ILLMProvider, IRagProvider, IContextCompressor, IOperator, IMcpClient, ...

🤝 Участие в разработке

Мы приветствуем вклад! Пожалуйста, прочитайте CONTRIBUTING.md для рекомендаций по настройке окружения разработки, стандартам кодирования и процессу pull-request.


📄 Лицензия

Delibera распространяется под лицензией MIT.

Copyright © 2026 Delibera Project.


⚖️ Delibera — Продуманные решения с помощью ИИ

Создано с заботой о коллективном интеллекте на базе ИИ