Skip to content

techbuzzz/Delibera

Repository files navigation

Delibera

Delibera

βš–οΈ Thoughtful AI Decisions

Collective decision making through structured AI deliberation β€” with RAG, pgvector, Knowledge Keeper, πŸ› οΈ Operator (MCP tools), Chairman, πŸ”₯ Context Compression, βœ‚οΈ AutoChunking, πŸ’‰ Dependency Injection & πŸ“‹ Execution Logging

NuGet License: MIT .NET 10 C# 15

EN / RU


πŸ“– Overview

Delibera is a C# / .NET 10 framework that orchestrates multi-model deliberations between LLMs. Multiple AI models reason through a question across structured rounds, critique each other's answers, and a Chairman weighs the arguments to synthesise a balanced final verdict β€” enriched by a Knowledge Keeper backed by Qdrant or PostgreSQL/pgvector (RAG), with intelligent context compression to minimise token usage.

The name comes from deliberation β€” the careful weighing of evidence and viewpoints before reaching a decision. Delibera brings that discipline to AI, helping teams reach thoughtful, well-reasoned outcomes rather than single-model guesses.


✨ Key Features

Feature Description
πŸ›οΈ Multi-Model Councils Orchestrate any number of LLM participants across structured debate rounds
βš–οΈ Chairman Synthesis A dedicated moderator opens, regulates, and synthesises the final verdict
πŸ“š Knowledge Keeper (RAG) Per-round semantic retrieval with structured, cited responses
πŸ› οΈ Operator (MCP Tools) A micro-agent that delegates tasks to MCP servers (web, files, Marp, Notion, …) on demand during the debate
🐘 Qdrant + pgvector Pluggable vector stores β€” use a dedicated DB or your existing PostgreSQL
πŸ—œοΈ Context Compression 4 strategies (Semantic, Deduplication, Summarization, Hybrid) save 30–70% of tokens
βœ‚οΈ AutoChunking Progressive disclosure of large documents across rounds β€” respects model context windows
πŸ’‰ Dependency Injection AddDelibera() extension for IServiceCollection with full options binding
πŸ“‹ Execution Logging ExecutionLog model with LogLevel β€” Chairman, KK, Compression & participant events
πŸ“ Separate File Output Export result.md, statistics.md, and logs.md independently
πŸ”Œ Interface-First Clean abstractions for providers, factories, builders and executors
🀝 Microsoft.Extensions.AI First-class support for IChatClient / IEmbeddingGenerator β€” plug in OpenAI, Azure OpenAI, Ollama or any compatible backend, with middleware (function calling, logging)
πŸ›‘ Cooperative Cancellation Every public async method accepts a CancellationToken; a host shutdown or user cancel aborts the debate mid-flight (rounds, LLM calls, MCP tools, RAG, file saves)
🧱 Modern C# 15 (preview) Built on .NET 10 with LangVersion=preview, file-scoped namespaces, records, span/SIMD hot paths

πŸ†• What's new in v10.2.6

Feature Description
🌊 Async Streaming Council ICouncilExecutor.StreamDebateAsync yields each DebateRound live via an internal Channel<DebateRound> bridge β€” perfect for ASP.NET Core SSE, WebSocket, Blazor, and CLI live output. DebateRound.Total + IsFinal + LastStreamedResult round metadata included.
πŸ—³οΈ Pluggable Vote Engine IVotingStrategy with built-in MajorityVotingStrategy, BordaCountVotingStrategy, WeightedVotingStrategy (per-member MemberWeights). Chairman.CreateVoting(...) swaps the synthesis path for a verifiable decision tally rendered as a πŸ—³οΈ Voting Tally section in the Markdown output.
πŸ’Ύ Debate Persistence & Resume IDebateStore + FileDebateStore (atomic JSON write-then-rename, RetentionDays) + InMemoryDebateStore. CouncilBuilder.WithPersistence(...) saves a checkpoint after every round; ResumeFrom(debateId) continues from the last completed round after a crash or pause.
🧠 Agent Memory IAgentMemory with InMemoryAgentMemory (Jaccard similarity), QdrantAgentMemory (per-agent collection), PgVectorAgentMemory (shared table filtered by agent_name). CouncilBuilder.WithAgentMemory(...) recalls before + persists after every debate.
πŸ“Š OpenTelemetry-style Observability DeliberaActivitySource + DeliberaMeter with histograms, counters, and gauge for spans like delibera.council.execute, delibera.council.round, delibera.compression. Zero-overhead when no listener is attached. CouncilBuilder.WithTelemetry(...) enables it.
πŸ“‹ Structured Output IStructuredOutputSerializer + JsonSchemaOutputSerializer (uses .NET 10 JsonSchemaExporter). ICouncilExecutor.ExecuteTypedAsync<TVerdict> returns a strongly-typed verdict deserialised from the Chairman's response. One automatic retry on deserialisation failure.
πŸ”„ Adaptive Strategy Switching IStrategySelector + AdaptiveStrategySelector swap the debate strategy mid-flight when responses stagnate (StagnationThreshold consecutive low-diversity rounds, Levenshtein fallback when no embedding provider).
πŸ“‹ Debate Templates 6 built-in templates (DebateTemplate.ArchitectureReview, RiskAssessment, CodeReview, ProductDecision, SecurityAudit, DataArchitecture) with pre-configured participants, personas, strategies, and chairmen.
⚑ Quick Wins DebateResult.ToHtml() + SaveToHtmlAsync(); CouncilBuilder.WithTimeout(TimeSpan); Persona presets; CouncilBenchmark for side-by-side model comparison; WithParticipantLimit(int) safety guard.

See CHANGELOG.md for the full v10.2.6 release notes and docs/v10.2.6.md for the original roadmap.


πŸ“‘ Table of Contents


πŸš€ Quick Start

Prerequisites & Models

  • .NET 10 SDK (β‰₯ 10.0.301) β€” the project targets net10.0 and builds with LangVersion=preview to enable C# 15 features. See docs/NET10-Upgrade.md for the full migration notes.
  • A running Ollama instance β€” local (ollama serve) or Ollama Cloud (just an API key, no install).
  • The minimal set of models listed below.
  • Optional β€” for the Operator role: Node.js + npx to launch MCP servers (e.g. @playwright/mcp, @marp-team/marp-cli). See Operator (MCP Tools).

🟒 Minimal β€” for a tiny debate (β‰ˆ 2 GB total)

Suitable for smoke-testing, low-end hardware, and quick CLI runs.

Purpose Model Size Pull command
Council member llama3.2:1b 1.3 GB ollama pull llama3.2:1b
Council member qwen2.5:1.5b 1.1 GB ollama pull qwen2.5:1.5b
Embeddings (RAG) nomic-embed-text 274 MB ollama pull nomic-embed-text

🟑 Standard β€” recommended for most use cases (β‰ˆ 7 GB total)

Good reasoning quality with low latency. This is the default set used throughout the README.

Purpose Model Size Pull command
Council member llama3.2:3b 2.0 GB ollama pull llama3.2:3b
Council member qwen2.5:7b 4.7 GB ollama pull qwen2.5:7b
Embeddings (RAG) nomic-embed-text 274 MB ollama pull nomic-embed-text

πŸ”΄ High-Performance β€” for production-grade deliberations (β‰ˆ 30+ GB)

Heavier local models, recommended on GPUs with β‰₯ 24 GB VRAM or on Ollama Cloud.

Purpose Model Size Pull command
Council member llama3.1:8b 4.9 GB ollama pull llama3.1:8b
Council member qwen2.5:14b 9.0 GB ollama pull qwen2.5:14b
Council member mistral:7b 4.4 GB ollama pull mistral:7b
Chairman qwen2.5:14b (or larger) 9.0 GB ollama pull qwen2.5:14b
Embeddings (RAG) nomic-embed-text 274 MB ollama pull nomic-embed-text

πŸ’‘ Ollama Cloud has the same model names but doesn't require local disk space β€” you only need an API key. See the Configuration section for setting it.

Installation

dotnet add package Delibera.Core

Minimal Example

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);

πŸ“„ See docs/QuickStart.md for a step-by-step walkthrough.

Run

dotnet run

Delibera will run a structured, multi-round debate and write the full transcript and the Chairman's verdict to deliberation.md.


πŸ’‰ Dependency Injection

Register all Delibera services in one line:

using Delibera.Core.DependencyInjection;

// Option A: With configuration binding (binds the "Delibera" section)
services.AddDelibera(configuration, "Delibera");

// Option B: With options delegate
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;
});

// Option C: Defaults only
services.AddDelibera();

Resolves these interfaces from DI:

Interface Implementation Lifetime
ILLMProviderFactory ProviderFactory Singleton
IRagProviderFactory RagProviderFactory Singleton
ICompressionFactory CompressionService Singleton
ICouncilBuilder CouncilBuilder Transient

Configuration (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
    }
  }
}

To use Ollama Cloud, set Providers:DefaultEndpoint to https://api.ollama.com and put your key in Providers:ApiKey (or OllamaCloud:ApiKey in the DeliberaApp section used by the console app β€” see ConsoleApp Examples).


πŸ› οΈ Operator (MCP Tools)

The Operator is a lightweight micro-agent that connects the council to the outside world through MCP (Model Context Protocol) servers. It exposes whatever tools those servers provide β€” web browsing, file system access, Marp presentation generation, Notion, PostgreSQL, etc. β€” to the debate participants.

How it works

  1. The Operator connects to one or more MCP servers and discovers their tools on InitializeAsync.

  2. Participants are told (in their system prompt) what the Operator can do, and can delegate a task at any moment during the debate by writing a marker in their message:

    [[OPERATOR: open https://modelcontextprotocol.io and summarize what MCP is]]
    
  3. The Operator interprets the request with its own (cheaper) LLM model, picks and calls the right MCP tools, interprets the results, and returns a concise answer that is injected into the next round.

  4. If the council uses context compression, the Operator can reuse the same strategy to compress large tool outputs before they re-enter the debate. Its DisposeAsync is a ValueTask (.NET 10 IAsyncDisposable) so MCP clients are released without a Task allocation.

All Operator interactions are recorded per round and rendered in the final Markdown report under a πŸ› οΈ Operator Interactions block.

Configuring MCP servers

using Delibera.Core.Models;

var servers = new[]
{
    // stdio transport β€” launches a local MCP server process
    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" }),

    // …or an HTTP/SSE transport for a remote MCP server
    // McpServerConfig.Http(
    //     name: "remote",
    //     endpoint: "https://my-mcp-host.example.com/mcp",
    //     additionalHeaders: new Dictionary<string, string> { ["Authorization"] = "Bearer <token>" }),
};
Server Transport Launch command What it provides
🌐 browser stdio npx -y @playwright/mcp@latest --headless Site navigation, page reading, clicks, screenshots
🎯 marp stdio npx -y @marp-team/marp-cli --server <dir> Generating presentations (HTML/PDF/PPTX) from Markdown

Quick usage (inside a council)

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 uses its own cheaper model; reuseCompression shares the council's compressor
    .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();

Prefer to build the Operator yourself? Pass a pre-built instance:

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,            // optional IContextCompressor
    compressionOptions: null);   // optional CompressionOptions

var council = new CouncilBuilder()
    /* …members… */
    .WithOperator(@operator)
    .Build();

Direct usage (without a council)

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

Configure the Operator declaratively in appsettings.json under 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>" }
        }
      ]
    }
  }
}

▢️ A complete, runnable demo lives in OperatorMcpToolsExample.cs. Run it with dotnet run --project src/Delibera.ConsoleApp -- --operator-mcp. For the full technical write-up, see docs/NET10-Upgrade.md.


πŸ—œοΈ Context Compression

Automatically compress context between deliberation rounds β€” save 30–70% of tokens without losing meaning.

Strategy How It Works Best For
Semantic Embeds sentences, ranks by relevance to topic, keeps top-N Large knowledge contexts
Deduplication Removes semantically similar sentences across participants Multi-model debates with overlap
Summarization LLM produces a concise summary preserving key facts Maximum compression ratio
Hybrid Dedup β†’ Semantic β†’ Summarize pipeline Best overall quality
None Pass-through (when disabled) Debugging
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());

Compression Pipeline

IContextCompressor
β”œβ”€β”€ SemanticCompressor        ← Embedding-based sentence ranking
β”œβ”€β”€ DeduplicationCompressor   ← Similarity-based duplicate removal
β”œβ”€β”€ SummarizationCompressor   ← LLM-powered summarization
β”œβ”€β”€ HybridCompressor          ← Multi-stage pipeline (Dedup β†’ Semantic β†’ Summarize)
└── PassThroughCompressor     ← No-op (when disabled)

CompressionFactory            ← Static factory (Create by enum or string)
CompressionService            ← DI-friendly wrapper around CompressionFactory
CompressionCache              ← SHA-256 keyed LRU cache
TokenCounter                  ← Heuristic token estimation

βœ‚οΈ AutoChunking

Automatically split large knowledge documents (contracts, reports, articles) into context-window-sized chunks distributed across debate rounds via progressive disclosure. When a document exceeds the smallest model's context window, the orchestrator creates a chunking plan and distributes chunks evenly β€” every model receives a complete view by the final round.

How it works

  1. Model discovery β€” queries each model's context window via GetModelCapabilitiesAsync() (Ollama /api/show, or the built-in registry of 40+ models).
  2. Overhead calculation β€” system prompt + user question + response buffer + history.
  3. Chunking plan β€” splits the document on semantic boundaries (Markdown headers β†’ paragraphs β†’ sentences), each chunk ≀ minWindow βˆ’ overhead βˆ’ safetyMargin.
  4. Progressive disclosure β€” Round 1 gets chunks 1..N/3, Round 2 gets N/3+1..2N/3, etc. Each round sees [Chunk X/Y] SectionTitle markers + a summary of previous rounds.

Three configuration paths

// Path 1: Fluent API
var executor = new CouncilBuilder()
    .WithAutoChunking(new AutoChunkingOptions
    {
        Strategy = ChunkingStrategy.SemanticBoundary,
        SafetyMargin = 0.15,
        MaxChunksPerRound = 3
    })
    /* …members, chairman, knowledge… */
    .Build();

// Path 2: CouncilOptions snapshot (from DI or manual)
var options = new CouncilOptions
{
    AutoChunking = new AutoChunkingConfig { Enabled = true, Strategy = "SemanticBoundary" }
};
var executor = new CouncilBuilder(options)  // or .WithOptions(options)
    /* … */
    .Build();

// Path 3: Lambda configuration
var executor = new CouncilBuilder()
    .WithOptions(o =>
    {
        o.AutoChunking.Enabled = true;
        o.AutoChunking.MaxChunksPerRound = 2;
    })
    /* … */
    .Build();

Configuration (appsettings.json)

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

Model Context Window Registry

// Query known models
var window = ModelContextWindowRegistry.GetContextWindow("llama3.2"); // β†’ 131072
var window = ModelContextWindowRegistry.GetContextWindow("phi3:mini"); // β†’ 4096

// Register custom models
ModelContextWindowRegistry.Register("my-fine-tuned-model", 65536);

▢️ Run the demo: dotnet run --project src/Delibera.ConsoleApp -- --autochunking


πŸ“š RAG Integration

Use a dedicated Qdrant instance or your existing PostgreSQL/pgvector database as a vector store.

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 β€” just add a connection string
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);

// Wire into a 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

The Knowledge Keeper is then attached to the council via WithKnowledgeKeeper(...) β€” see the RAG example for a full working demo.


πŸ—£οΈ Debate Strategies

Strategy Flow Use Case
StandardDebate Initial β†’ Critique β†’ Improved β†’ Verdict General analysis
CritiqueDebate Position β†’ Attack β†’ Defence β†’ Judge Hypothesis testing
ConsensusDebate Perspectives β†’ Common Ground β†’ Consensus β†’ Facilitator Optimal solution search

Each strategy is implemented as an IDebateStrategy β€” see src/Delibera.Core/Debate/ for the full source.

Design Patterns

Pattern Usage
Factory ProviderFactory, RagProviderFactory, CompressionFactory, Chairman
Strategy IDebateStrategy, IContextCompressor
Builder CouncilBuilder fluent API
Template Method DebateScenario abstract base class
Cache CompressionCache with SHA-256 keys
Observer OnRoundCompleted event on CouncilExecutor

πŸ“ Output Files Structure

Each deliberation can be exported as a single file or as three separate Markdown documents:

var result = await executor.ExecuteAsync();

// Save to 3 separate files
var (resultPath, statsPath, logsPath) = await result.SaveAllAsync("./output");
// Creates: debate_20260604_120000_result.md
//          debate_20260604_120000_statistics.md
//          debate_20260604_120000_logs.md

// Or save individually
await result.SaveToMarkdownAsync("result.md");
await result.SaveStatisticsAsync("statistics.md");
await result.SaveLogsAsync("logs.md");
File Contents
*_result.md Full deliberation transcript, rounds, and the Chairman's final verdict
*_statistics.md Token usage statistics with per-round breakdown
*_logs.md Execution logs (ExecutionLog) for Chairman, KK, compression & participants

πŸ›‘ Cancellation Support

Every public async method in Delibera honors a CancellationToken cooperatively. A single cancel signal aborts the entire pipeline β€” rounds, chairman synthesis, LLM calls, MCP tools, RAG queries and even file writes β€” via OperationCanceledException.

using var cts = new CancellationTokenSource(TimeSpan.FromMinutes(5));
var result = await executor.ExecuteAsync(cts.Token);

ASP.NET Core / Worker Services can link the token to IHostApplicationLifetime.ApplicationStopping via the Delibera.Core.Extensions.CouncilExecutorLifetimeExtensions.ExecuteAsync(executor, lifetime, ct) helper. Console apps can wire Console.CancelKeyPress to the same CancellationTokenSource.

The Delibera.ConsoleApp includes a --cancellation demo that exercises this end-to-end.

See the Cancellation section in Delibera.Core README for the full table of cancellable operations and the linked-token pattern.


πŸ’» ConsoleApp Examples

The repository ships with Delibera.ConsoleApp, a runnable demo project that exercises every feature. Run it from the repo root:

# Clone the repository
git clone https://github.com/delibera/Delibera.git
cd Delibera/src/Delibera.ConsoleApp

# Run a specific example
dotnet run -- --di                 # Dependency Injection
dotnet run -- --separate-files     # Save result.md, statistics.md, logs.md
dotnet run -- --compression        # Context compression demo
dotnet run -- --multiprovider      # Multi-provider (cloud + local) council
dotnet run -- --rag                # Qdrant-backed RAG with Knowledge Keeper
dotnet run -- --pgvector           # pgvector-backed RAG
dotnet run -- --operator           # Operator role basics (MCP tools)
dotnet run -- --operator-mcp       # πŸ†• Operator with browser + Marp MCP servers
dotnet run -- --autochunking       # πŸ†• AutoChunking demo (large documents)

# Or run the full default demo (reads appsettings.json)
dotnet run

The console app reads appsettings.json which uses the DeliberaApp section β€” by default it points at Ollama Cloud and shows you how to wire multiple providers, RAG, and compression in one place.


πŸ› οΈ Installation & Build

Clone & Build

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

# Build the entire solution
dotnet build --configuration Release

# Run the console demo
cd src/Delibera.ConsoleApp
dotnet run

One-Command Infrastructure (Docker Compose)

Spin up Qdrant + PostgreSQL/pgvector in one shot. (Ollama is intentionally not included β€” install it natively so the GPU driver is used directly.)

# From the repo root
docker compose up -d

# In another terminal, run the console app
cd src/Delibera.ConsoleApp
dotnet run

The compose stack exposes:

Service URL Purpose
Qdrant (REST) http://localhost:6333 Vector store UI / REST
Qdrant (gRPC) localhost:6334 gRPC client (used by Delibera)
PostgreSQL localhost:5432 pgvector RAG store

Default credentials: postgres / postgres, database council_vectors.

If you already have these services running natively, just skip docker compose and point the console app at them β€” appsettings.json defaults to localhost.

Manual Alternative (one container at a time)

# Run with Qdrant (Docker)
docker run -d -p 6333:6333 -p 6334:6334 qdrant/qdrant

# Run with pgvector (Docker)
docker run -d -p 5432:5432 -e POSTGRES_PASSWORD=postgres pgvector/pgvector:pg16

# Then enable the pgvector extension
docker exec -it <container> psql -U postgres -d council_vectors -c "CREATE EXTENSION IF NOT EXISTS vector;"

NuGet Dependencies

Package Purpose
OllamaSharp Ollama API client
Qdrant.Client Qdrant vector DB gRPC client
Npgsql PostgreSQL ADO.NET provider
Pgvector pgvector type support for Npgsql
ModelContextProtocol MCP client for the Operator role
Microsoft.Extensions.AI Unified IChatClient / IEmbeddingGenerator AI abstractions & middleware
Microsoft.Extensions.* Configuration, DI and Options

🀝 Microsoft.Extensions.AI

Delibera integrates with Microsoft.Extensions.AI (v10.7.0) β€” the standard .NET abstraction layer for generative-AI services. This lets you drive a council with any backend that ships an IChatClient (OpenAI, Azure OpenAI, Ollama, Anthropic, LM Studio / LocalAI / vLLM, …) and compose a middleware pipeline (function/tool invocation, logging, caching, telemetry) β€” all without writing a provider per vendor.

What you get

Type Role
ChatClientLLMProvider Adapts any IChatClient to Delibera's ILLMProvider (with streaming via ChatStreamAsync)
EmbeddingGeneratorProvider Adapts any IEmbeddingGenerator<string, Embedding<float>> to IEmbeddingProvider for RAG
MicrosoftAIExtensions Bridge helpers: AsLLMProvider(), AsEmbeddingProvider(), AsChatClient(), WithMiddleware()
ProviderFactory.CreateFromChatClient(...) Build a cached provider straight from an IChatClient
AddDeliberaChatClient(...) / AddDeliberaEmbeddingGenerator(...) Register the standard AI services in DI

Use any IChatClient as a Delibera provider

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

// 1) Bring your own IChatClient. For OpenAI:
//    dotnet add package Microsoft.Extensions.AI.OpenAI
IChatClient client = new OpenAI.Chat.ChatClient("gpt-4o-mini", apiKey).AsIChatClient();

// 2) (optional) compose middleware β€” function calling + logging
client = client.WithMiddleware(enableFunctionInvocation: true, loggerFactory);

// 3) expose it to Delibera
ILLMProvider provider = client.AsLLMProvider("OpenAI");

var executor = new CouncilBuilder()
   .AddMember("gpt-4o-mini", provider, "Architect")
   .AddMember("gpt-4o-mini", provider, "Skeptic")
   .SetChairman(Chairman.CreateStandard("gpt-4o-mini", provider))
   .WithStandardDebate()
   .WithUserPrompt("Modular monolith or microservices for a 5-person team?")
   .Build();

Ollama works out of the box because OllamaSharp's OllamaApiClient natively implements IChatClient and IEmbeddingGenerator:

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

Streaming

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

ChatStreamAsync is an additive default method on ILLMProvider β€” providers backed by an IChatClient stream token-by-token, while older providers transparently fall back to a single call.

Dependency Injection

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

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

Try it: dotnet run --project src/Delibera.ConsoleApp -- --msai


πŸ›οΈ Architecture

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 servers)
β”œβ”€β”€ Extensions/           ← MicrosoftAIExtensions (IChatClient ↔ ILLMProvider bridges)
β”œβ”€β”€ DependencyInjection/  ← AddDelibera() / AddDeliberaChatClient() + CouncilOptions
β”œβ”€β”€ Knowledge/            ← MarkdownKnowledgeBase
β”œβ”€β”€ Models/               ← CouncilMember, DebateResult, DebateRound, TokenStatistics, ...
└── Interfaces/           ← ILLMProvider, IRagProvider, IContextCompressor, IOperator, IMcpClient, ...

🀝 Contributing

Contributions are welcome! Please read CONTRIBUTING.md for guidelines on development setup, coding standards, and the pull-request process.


πŸ“„ License

Delibera is released under the MIT License.

Copyright Β© 2026 Delibera Project.


βš–οΈ Delibera β€” Thoughtful AI Decisions

Built with care for AI-powered collective intelligence

About

Delibera - Thoughtful AI Decisions. A framework for collective decision making through structured AI deliberation. Supports multi-model councils with RAG (Qdrant, PgVector), debate strategies, Knowledge Keeper, Chairman roles, dependency injection, and context compression.

Topics

Resources

License

Contributing

Stars

3 stars

Watchers

0 watching

Forks

Packages

 
 
 

Contributors

Languages