惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

Apple Machine Learning Research
Apple Machine Learning Research
AWS News Blog
AWS News Blog
Google DeepMind News
Google DeepMind News
U
Unit 42
博客园 - 叶小钗
博客园 - 聂微东
GbyAI
GbyAI
Stack Overflow Blog
Stack Overflow Blog
有赞技术团队
有赞技术团队
aimingoo的专栏
aimingoo的专栏
D
DataBreaches.Net
CTFtime.org: upcoming CTF events
CTFtime.org: upcoming CTF events
Jina AI
Jina AI
美团技术团队
The Cloudflare Blog
M
MIT News - Artificial intelligence
Microsoft Azure Blog
Microsoft Azure Blog
I
InfoQ
S
Schneier on Security
C
Check Point Blog
Project Zero
Project Zero
The Hacker News
The Hacker News
Scott Helme
Scott Helme
K
KPMG report finds enterprise disconnect between AI and its ROI | CIO
Cisco Talos Blog
Cisco Talos Blog
P
Privacy International News Feed
SecWiki News
SecWiki News
Latest news
Latest news
MongoDB | Blog
MongoDB | Blog
S
Secure Thoughts
Google Online Security Blog
Google Online Security Blog
F
Fortinet All Blogs
博客园 - 三生石上(FineUI控件)
H
Help Net Security
TaoSecurity Blog
TaoSecurity Blog
cs.CL updates on arXiv.org
cs.CL updates on arXiv.org
Last Week in AI
Last Week in AI
P
Privacy & Cybersecurity Law Blog
Forbes - Security
Forbes - Security
G
GRAHAM CLULEY
N
Netflix TechBlog - Medium
L
Lohrmann on Cybersecurity
A
About on SuperTechFans
T
The Exploit Database - CXSecurity.com
C
Cisco Blogs
PCI Perspectives
PCI Perspectives
大猫的无限游戏
大猫的无限游戏
T
Troy Hunt's Blog
H
Hacker News: Front Page
Vercel News
Vercel News

DEV Community

Authentication Security Deep Dive: From Brute Force to Salted Hashing (With Java Examples) Why AI Systems Don’t Fail — They Drift Spilling beans for how i learn for exam😁"Reinforcement Learning Cheat Sheet" I Replaced Chrome with Safari for AI Browser Automation. Here's What Broke (and What Finally Worked) How Python Borrows Other People's Work The $40 Architecture: Processing 1 Billion API Requests with 99.99% Uptime Vibe Coding: A Workflow Guide (From Zero to SaaS) Most webhook security guides protect the wrong side. The scary part is delivery. Headless CMS for TanStack Start: Build a Blog with Cosmic EU Age Verification App "Hacked in 2 Minutes" — What Actually Happened Comfy Cloud’s delete function does not actually remove files Running AI Models on GPU Cloud Servers: A Beginner Guide Event-driven media intelligence with AWS Step Functions and Bedrock I scored 500 AI prompts across 8 quality dimensions — here's what broke How to Call Google Gemini API from Next.js (Free Tier, No Backend Needed) The Portal Protocol: Reclaiming Human Connection in the Age of AI How to Fix Your Team's Scattered Knowledge Problem With a Self-Hosted Forum Intro to tc Cloud Functors: A Graph-First Mental Model for the Modern Cloud Designing Multi-Tenant Backends With Both Ownership and Team Access I Built a Neumorphic CSS Library with 77+ Components — Here's What I Learned PostgreSQL Performance Optimization: Why Connection Pooling Is Critical at Scale Cómo construí un SaaS multi-rubro para gestionar expensas en Argentina con FastAPI + Vue 3 🚀 I Built an Ethical Hacking Scanner Tool – Open Source Project I Replaced /usage and /context in Claude Code With a Single Statusline A Pythonic Way to Handle Emails (IMAP/SMTP) with Auto-Discovery and AI-Ready Design I Collected 8.9 Million Polymarket Price Points — Here's What I Found About How Markets Really Move EcoTrack AI — Carbon Footprint Tracker & Dashboard Everyone's Using AI. No One Agrees How. 5 self-hosted ebook managers worth trying in 2026 Building Your First AI Agent with LangChain: From Chatbot to Autonomous Assistant Common SOC 2 Failures (Real World) Stop Vibe-Checking Your AI App: A Practical Guide to Evals How to Use SonarQube and SonarScanner Locally to Level Up Your Code Quality Your Next To-Do App Is Dead — I Replaced Mine with an OpenClaw AI Sign a Nostr event in 60 lines of Python using coincurve — no nostr-sdk, no nbxplorer, no rust toolchain ITGC Audit Explained Like You’re in Big 4 Patch Tuesday abril 2026: Microsoft parcha 163 vulnerabilidades y un zero-day en SharePoint Stop scraping everything: a better way to track competitor price changes Listing on MCPize + the Official MCP Registry while routing payments OUTSIDE the marketplace — how I kept 100% of my x402 revenue Building an AI-Powered Risk Intelligence System Using Serverless Architecture Why We Ripped Function Overloading Out of Our AI Toolchain Testing AI-Generated Code: How to Actually Know If It Works SaaS Churn Is Killing Your Business. Here Is What to Do About It (Without a Support Team) The Speed of AI Is No Longer Linear - And Self-Improving Models Are Why How to Implement RBAC for MCP Tools: A Practical Guide for Engineering Teams From Standard Quote to Persuasive Proposal: AI Automation for Arborists I built a CLI that scaffolds complete multi-tenant SaaS apps Axios CVE-2025–62718: The Silent SSRF Bug That Could Be Hiding in Your Node.js App Right Now The dashboard that ended our friendship Data Pipelines Explained Simply (and How to Build Them with Python) The Hidden Cost of AI Systems Nobody Talks About. undefined vs undeclared, and how typeof behaves Switching from file-based jobs to NATS/Kafka in Rust without changing code io_uring Adventures: Rust Servers That Love Syscalls Why Agentic AI is Killing the Traditional Database The POUR principles of web accessibility for developers and designers Quantum Neural Network 3D — A Deep Dive into Interactive WebGL Visualization How To Install Caveman In Codex On macOS And Windows Automation Pipeline Reliability: Why Your Workflow Breaks When Nobody Is Watching I Built an 'Open World' AI Coding Agent — It Works From ANY Folder From Freelancing to Product: A Tech Service Company's SaaS Transformation China's AI Giants: Adding Tencent Hunyuan & ByteDance Doubao to AI University (74 Providers) On the Vibe Coders and Their Lies clerk: Auto-Summarize Your Claude Code Sessions AI Weekly — 2026/04/10–04/17 | The Model Lockdown Is Here, but the Toolchain Is the Real Battleground AI 週報 — 2026/04/10–2026/04/17 模型封鎖潮來了,但工具鏈才是真戰場 Maybe this is how Open-Source apps are born... 🚀 Fine-Tune LLMs with LoRA and QLoRA: 2026 Guide tRPC v11 + Next.js App Router: End-to-End Type Safety Without the Boilerplate ShadCN UI in 2026: Why I Stopped Installing Component Libraries and Started Owning My Components SaaS Billing in React Server Components: Stripe + Supabase Without a Single `useEffect` Join our DEV Weekend Challenge — $1,000 in Prizes Across TEN winners! Submissions Due April 20 at 6:59 AM UTC. Implementing FSRS Spaced Repetition in Flutter + Supabase — Adding Memory Science to an AI Learning App "I Texted My Localhost From the Train — Claude Code Fixed the Bug Before I Got Home" I Built a Sales Prep AI and It Went Deeper Than Expected Design to Code #2: One JSON, Eleven Outputs Solving the 100M-Row Problem: A Summary Table Pattern for High-Volume Push Notification Logs Flutter Web With Wasm: What Actually Changes For Developers I Built 50 Royalty-Free Soundtracks for My Side Project in a Weekend Using AI Music Generation The Vibe Coding Security Checklist: 7 Things to Check Before You Ship Stop Letting Googlebot Guess Fix Your React App's SEO Right Desconstruindo o Streaming do LinkedIn: Como Criar um Engine de Extração de Vídeo de Alta Performance com HLS e FFmpeg (EDA Part-1) EDA (Exploratory Data Analysis) Explained With Real Life — Why Looking at Your Data Is the Most Important Step in Machine Learning Brand Relationship Management at Scale: Our 4-Touch Outreach System for 200+ Brands Why String.fromEnvironment() Might Return an Empty String in Dart JGuardrails 1.0.0 — Hardening Java LLM Apps Against Jailbreaks, Toxicity, and Prompt Injection Plan and Schedule a Full Week of Threads Content From One Claude Conversation Coding Cat Oran Ep3, Five Tables Changed Everything Updated: BFF Pattern I'm done watching freelancers get buried by 200 proposals. So I'm building the alternative. This is my first post BFS Algorithm in Java Step by Step Tutorial with Examples Tracking LLM Pricing Monthly: An Open Dataset for 22 AI Models How We Measure Content ROI on a Comparison Site: Revenue Attribution Without Perfect Data Introducing Nova AI Ops: The AI-Native Operating System for SRE Teams I built a free desktop video downloader for Windows — Grabbit How Talkie OCR Helps Vision-Impaired & Dyslexic Users Read the World Around Them VRCFaceTracking安装和iPhone面捕配置教程,有bug Even CrowdStrike Can't See Your Agents The Automation Gold Rush: What n8n Workflows and Claude Are Opening Up for Developers Right Now
Forget Your RAG: Build Your Own LLM Wiki in C# with Ollama + Kimi (Step‑by‑Step Guide)
David Au Yeu · 2026-05-06 · via DEV Community

Introduction

Happy coding! Today I want to share a practical AI tutorial in .NET style, with real code, simple architecture, and a result you can run on your own machine.

When many developers start building AI knowledge assistants, the first idea is usually RAG. That is a good choice in many cases, but not always the simplest one. Sometimes, your knowledge base is actually small, focused, and stable. In that lovely situation, building a small LLM Wiki can be a more elegant choice.

Let me tell a short lovely story.

Imagine a small tea house run by a kind grandmother. Every morning, her grandchildren ask the same questions:

  • Which tea is good for a cold day?
  • Which dessert has nuts?
  • What is the house special today?

Now imagine two ways to help them.

  1. The first way is to hire a fast librarian who runs to a giant archive room every time a child asks a question. That is a bit like RAG.
  2. The second way is to write one beautiful, well-organized family handbook and keep it on the table all the time. That is a bit like an LLM Wiki.

If the tea house menu is small and stable, the handbook is often faster, simpler, and more reliable. But if the tea house becomes a huge restaurant chain with thousands of daily updates, you will eventually want the librarian too.

That is the heart of LLM Wiki vs RAG.

In this tutorial, we will build an open-source local LLM Wiki demo in C# using:

  • .NET 8
  • Ollama
  • OllamaSharp
  • a local markdown-based wiki structure
  • the kimi-k2.6:cloud Ollama model

By the end, you will have:

  • a console-based demo app
  • a LocalWiki folder with markdown files
  • document ingestion logic
  • index maintenance logic
  • wiki question-answering logic
  • a clear understanding of when to use a wiki instead of RAG

What We Are Building

We are building a small local AI workflow like this:

  1. Prepare a source document.
  2. Send that document to an LLM through Ollama.
  3. Ask the LLM to return structured wiki content.
  4. Save the result as markdown in a local wiki folder.
  5. Update Index.md automatically.
  6. Ask questions against the wiki content.
  7. Let the model answer using the wiki instead of the raw source file.

This is not a full vector database pipeline. It is intentionally lighter.

LLM Wiki vs RAG

Before we code, let us understand the design choice.

What is RAG?

Retrieval-Augmented Generation (RAG) improves LLM output by retrieving relevant information from external sources before generating a response. Instead of depending only on training data, the model gets fresh context from documents, databases, or web content.

Common characteristics of RAG:

  • dynamic retrieval at question time
  • usually based on chunking + embeddings + vector search
  • good for large and changing knowledge bases
  • better for source attribution and enterprise-scale search
  • more infrastructure and tuning effort

What is an LLM Wiki?

An LLM Wiki is a curated, structured markdown knowledge base written so the model can reason over it directly. Rather than retrieving many chunks at runtime, you keep important domain knowledge in concise markdown files and pass those files into the model context.

Common characteristics of an LLM Wiki:

  • markdown-first knowledge organization
  • compact, human-readable, and model-friendly
  • great for small and stable domains
  • simple to maintain for focused use cases
  • low setup cost compared with a full RAG pipeline

When should you use a Wiki instead of RAG?

A wiki is a strong choice when:

  • your knowledge base is relatively small
  • your content changes slowly
  • you want to ship fast
  • you prefer markdown and file-based maintenance
  • you want fewer moving parts
  • you are building a demo, prototype, internal assistant, or focused domain tool

RAG is usually better when:

  • you have a very large knowledge base
  • documents change frequently
  • you need deep retrieval across many domains
  • you need richer source attribution and search behavior
  • your content does not fit comfortably into context

A practical rule of thumb

Start with an LLM Wiki if your knowledge is:

  • focused
  • stable
  • not too large
  • curated by humans or AI into clean markdown

Move to RAG when your knowledge becomes:

  • too large
  • too dynamic
  • too fragmented
  • too cross-domain

And yes, a hybrid approach is often best:

  • use a wiki for stable core knowledge
  • use RAG for large or fast-changing content

References and background reading

The ideas in this tutorial align with public explanations of RAG and LLM Wiki tradeoffs, including:

  • Wikipedia on Retrieval-Augmented Generation
  • AWS explanation of RAG and external knowledge grounding
  • MindStudio and 99helpers comparisons of LLM Wiki vs RAG for smaller knowledge bases

Prerequisites

Before we begin, make sure you have the following:

  • Visual Studio or another C# IDE
  • .NET 8 SDK
  • Ollama installed locally
  • the Kimi model available through Ollama
  • a Windows terminal or PowerShell

To use the model from this demo, run:

ollama run kimi-k2.6:cloud

Enter fullscreen mode Exit fullscreen mode

If Ollama is already running, that is enough for the demo.

Step 1: Create the Console App

If you want to build this from scratch in a new workspace, start with:

dotnet new console -n LLMWikiDemo
cd LLMWikiDemo

Enter fullscreen mode Exit fullscreen mode

In this project, the feature was added into an existing .NET 8 console app, but the same idea applies to a fresh app.

Step 2: Add the NuGet Package

Add OllamaSharp so your C# application can talk to Ollama:

dotnet add package OllamaSharp

Enter fullscreen mode Exit fullscreen mode

In this workspace, the project file already contains:

<PackageReference Include="OllamaSharp" Version="5.4.25" />

Enter fullscreen mode Exit fullscreen mode

Step 3: Define the Architecture

To keep the system architecture simple, we use these parts:

  • Program.cs as the entry point
  • LlmWikiManager.cs as the core service
  • LocalWiki/ as the generated markdown wiki
  • SCHEMA.md to define the wiki rules
  • Index.md as the article catalog
  • Articles/ for wiki pages

The flow is:

Source Document
    -> LlmWikiManager.IngestDocumentAsync(...)
    -> Ollama / Kimi model
    -> JSON-like structured response
    -> Markdown article
    -> Index.md update
    -> QueryWikiAsync(...)
    -> Answer from wiki context

Enter fullscreen mode Exit fullscreen mode

Step 4: Create the Wiki Manager

The main logic lives in Utils/LLMWikiManager.cs.

This class is responsible for:

  • creating the wiki folders
  • creating SCHEMA.md and Index.md
  • sending prompts to Ollama
  • parsing the model response
  • writing article markdown
  • reading article markdown back for Q&A

The manager constructor

We configure the Ollama endpoint and default model here:

public LlmWikiManager(
    string ollamaApiUrl = "http://localhost:11434",
    string modelName = "kimi-k2.6:cloud",
    string? wikiRootDirectory = null)
{
    _ollamaClient = new OllamaApiClient(new Uri(ollamaApiUrl))
    {
        SelectedModel = modelName
    };

    _wikiDirectory = wikiRootDirectory ?? Path.Combine(AppContext.BaseDirectory, "LocalWiki");
    _schemaFilePath = Path.Combine(_wikiDirectory, "SCHEMA.md");
    _indexFilePath = Path.Combine(_wikiDirectory, "Index.md");
    _articlesDirectory = Path.Combine(_wikiDirectory, "Articles");
}

Enter fullscreen mode Exit fullscreen mode

This means the wiki is generated near the app runtime folder, and the model defaults to kimi-k2.6:cloud.

Step 5: Bootstrap the Wiki Structure

We want the app to create the wiki structure automatically if it does not exist.

public async Task EnsureWikiStructureAsync()
{
    Directory.CreateDirectory(_wikiDirectory);
    Directory.CreateDirectory(_articlesDirectory);

    if (!File.Exists(_schemaFilePath))
    {
        await File.WriteAllTextAsync(_schemaFilePath, DefaultSchema);
    }

    if (!File.Exists(_indexFilePath))
    {
        var initialIndex = "# Local Wiki Index" + Environment.NewLine + Environment.NewLine;
        await File.WriteAllTextAsync(_indexFilePath, initialIndex);
    }
}

Enter fullscreen mode Exit fullscreen mode

This is one of the reasons the wiki approach feels nice. It is file-based, easy to inspect, and easy to explain.

Step 6: Stream Text from Ollama

OllamaSharp returns generation results as an async stream, so we collect the response text like this:

private async Task<string> GenerateTextAsync(string prompt)
{
    var builder = new StringBuilder();

    await foreach (var chunk in _ollamaClient.GenerateAsync(prompt))
    {
        if (!string.IsNullOrWhiteSpace(chunk?.Response))
        {
            builder.Append(chunk.Response);
        }
    }

    return builder.ToString();
}

Enter fullscreen mode Exit fullscreen mode

This is a small but important detail. If you try to await the sequence directly, the build will fail. You must use await foreach.

Step 7: Ingest a Source Document

Now comes the most interesting part.

When a source document arrives, we:

  1. read the file
  2. read the schema
  3. ask the model to return structured wiki data
  4. parse the result
  5. create a markdown article
  6. update Index.md

The ingestion prompt

The ingestion prompt in LlmWikiManager.cs looks like this:

var ingestionPrompt = $"""
    You are an AI assistant maintaining a markdown wiki.

    Schema:
    ---
    {schemaContent}
    ---

    Process this source document and respond with ONLY one JSON object using these keys:
    - summaryTitle: concise title for the article
    - summaryFilename: kebab-case markdown filename
    - summaryContent: full markdown article body
    - indexUpdate: one markdown bullet linking article from Index.md

    Source filename: {sourceFileName}
    Source document:
    ---
    {sourceContent}
    ---
 """;

Enter fullscreen mode Exit fullscreen mode

This is a practical pattern:

  • tell the model who it is
  • give it the wiki rules
  • give it the source content
  • enforce a structured output format

The ingestion method

A simplified view of the ingestion code:

public async Task<LlmWikiIngestionResult> IngestDocumentAsync(string sourceFilePath)
{
    await EnsureWikiStructureAsync();

    var sourceContent = await File.ReadAllTextAsync(sourceFilePath);
    var schemaContent = await File.ReadAllTextAsync(_schemaFilePath);
    var sourceFileName = Path.GetFileName(sourceFilePath);

    var responseText = await GenerateTextAsync(ingestionPrompt);
    var parsed = TryParseIngestionPayload(responseText);

    var summaryTitle = !string.IsNullOrWhiteSpace(parsed?.SummaryTitle)
        ? parsed!.SummaryTitle!
        : $"Summary of {Path.GetFileNameWithoutExtension(sourceFileName)}";

    var summaryFilename = NormalizeSummaryFilename(parsed?.SummaryFilename ?? string.Empty, summaryTitle);

    var summaryContent = !string.IsNullOrWhiteSpace(parsed?.SummaryContent)
        ? parsed!.SummaryContent!
        : BuildFallbackSummaryContent(sourceFileName, sourceContent);

    var summaryFilePath = Path.Combine(_articlesDirectory, summaryFilename);
    await File.WriteAllTextAsync(summaryFilePath, summaryContent);

    var normalizedRelativeArticlePath = $"Articles/{summaryFilename}";
    var indexUpdate = !string.IsNullOrWhiteSpace(parsed?.IndexUpdate)
        ? parsed!.IndexUpdate!.Trim()
        : $"- [{summaryTitle}]({normalizedRelativeArticlePath})";

    // append to Index.md if needed
}

Enter fullscreen mode Exit fullscreen mode

Why fallback logic matters

Real LLMs are helpful, but sometimes they do not follow the JSON contract perfectly.

That is why the demo includes:

  • JSON extraction from mixed text
  • deserialization attempts
  • fallback summary generation
  • filename normalization
  • index deduplication

This makes the POC stronger and more production-minded than a fragile one-shot prompt demo.

Step 8: Parse the LLM Response Safely

Structured AI output is never perfect, so the code extracts the JSON object defensively.

private static string? ExtractJsonObject(string text)
{
    if (string.IsNullOrWhiteSpace(text))
    {
        return null;
    }

    var start = text.IndexOf('{');
    var end = text.LastIndexOf('}');

    if (start < 0 || end <= start)
    {
        return null;
    }

    return text[start..(end + 1)];
}

Enter fullscreen mode Exit fullscreen mode

Then we try to deserialize it:

private static LlmWikiIngestionPayload? TryParseIngestionPayload(string responseText)
{
    var rawJson = ExtractJsonObject(responseText);
    if (rawJson is null)
    {
        return null;
    }

    try
    {
        return JsonSerializer.Deserialize<LlmWikiIngestionPayload>(rawJson, new JsonSerializerOptions
        {
            PropertyNameCaseInsensitive = true
        });
    }
    catch
    {
        return null;
    }
}

Enter fullscreen mode Exit fullscreen mode

This is a great lesson for readers: LLM output should be handled like user input. Trust it carefully, never blindly.

Step 9: Query the Wiki

Once the wiki exists, we can query it.

The app reads:

  • SCHEMA.md
  • Index.md
  • the latest markdown articles

Then it builds a prompt for the model.

public async Task<string> QueryWikiAsync(string question)
{
    await EnsureWikiStructureAsync();

    var schemaContent = await File.ReadAllTextAsync(_schemaFilePath);
    var indexContent = await File.ReadAllTextAsync(_indexFilePath);
    var articleContext = await BuildArticleContextAsync(maxArticles: 6, maxCharsPerArticle: 2400);

    var queryPrompt = $"""
        You are an AI assistant answering questions from a local markdown wiki.

        Rules:
        - Use only the provided wiki context.
        - If information is insufficient, explicitly say so.
        - Keep response concise.
        - Cite article filenames used as sources.

        Schema:
        ---
        {schemaContent}
        ---

        Index:
        ---
        {indexContent}
        ---

        Article context:
        ---
        {articleContext}
        ---

        Question: {question}
     """;

    var answer = (await GenerateTextAsync(queryPrompt)).Trim();

    if (string.IsNullOrWhiteSpace(answer))
    {
        return "Insufficient information in the wiki context to answer this question.";
    }

    return answer;
}

Enter fullscreen mode Exit fullscreen mode

This is a wiki-style answer flow, not a vector retrieval flow.

Step 10: Wire Everything in Program.cs

The entry point demonstrates the entire POC.

using MyPlaygroundApp.Utils;

class Program
{
    static async Task Main(string[] args)
    {
        Console.WriteLine("Open-Source LLM Wiki Demo (.NET + Ollama)");
        Console.WriteLine("------------------------------------------");
        Console.WriteLine();

        var wikiManager = new LlmWikiManager(modelName: "kimi-k2.6:cloud");
        await wikiManager.EnsureWikiStructureAsync();

        var demoInputDirectory = Path.Combine(AppContext.BaseDirectory, "DemoInput");
        Directory.CreateDirectory(demoInputDirectory);

        var sourceDocumentPath = Path.Combine(demoInputDirectory, "csharp-ai-benefits.txt");
        var sourceDocumentContent = """
            C# is effective for AI solution development due to strong typing, mature tooling, and excellent package management.
            The .NET ecosystem enables production-ready services, background workers, APIs, and cloud integration.
            Developers can integrate local LLMs using Ollama and open-source libraries such as OllamaSharp and Semantic Kernel.
            This approach is useful for private knowledge workflows like a local markdown wiki with ingestion and Q&A.
        """;

        await File.WriteAllTextAsync(sourceDocumentPath, sourceDocumentContent);

        Console.WriteLine("Ingesting source document into local wiki...");
        var ingestionResult = await wikiManager.IngestDocumentAsync(sourceDocumentPath);
        Console.WriteLine($"Article created: {ingestionResult.SummaryFilename}");
        Console.WriteLine($"Wiki location: {wikiManager.WikiDirectory}");
        Console.WriteLine();

        const string question = "What are the benefits of using C# for local LLM wiki development?";
        Console.WriteLine($"Question: {question}");
        var answer = await wikiManager.QueryWikiAsync(question);
        Console.WriteLine();
        Console.WriteLine("Answer:");
        Console.WriteLine(answer);

        Console.WriteLine();
        Console.WriteLine("Demo complete.");
    }
}

Enter fullscreen mode Exit fullscreen mode

This is excellent for a tutorial because readers can run it and immediately see the full loop.

Step 11: Run the Demo

From the solution root, run:

dotnet run --project .\MyPlaygroundApp\MyPlaygroundApp.csproj

Enter fullscreen mode Exit fullscreen mode

If Ollama is available and kimi-k2.6:cloud is usable, the demo should:

  • create the wiki structure
  • ingest the sample source document
  • write a markdown article
  • update the index
  • answer a question from the wiki context

Step 12: Show the Generated Wiki Files

These example results are perfect to show your readers.

Index.md

# Local Wiki Index

- [C# for AI Development](Articles/csharp-ai-development.md)

Enter fullscreen mode Exit fullscreen mode

SCHEMA.md

# LLM Wiki Schema

## Goal
Maintain a local markdown wiki from source documents.

## Ingestion Workflow
1. Read new source document.
2. Summarize key points with technical accuracy.
3. Create or update one markdown article in `Articles/`.
4. Ensure `Index.md` contains one bullet link per article.
5. Keep filenames kebab-case and `.md`.

## Query Workflow
1. Use only article/index content provided as context.
2. Answer concisely and cite article filenames used.
3. If context is insufficient, say information is insufficient.

Enter fullscreen mode Exit fullscreen mode

csharp-ai-development.md

# C# for AI Development

C# is a strong choice for building AI solutions, offering robust language features and a mature ecosystem.

## Key Advantages

- **Strong Typing & Tooling**: Static typing reduces runtime errors, while mature IDEs and debugging tools improve developer productivity.
- **Package Management**: NuGet provides reliable dependency management for complex projects.
- **Production-Ready Infrastructure**: The .NET ecosystem supports building scalable services, background workers, APIs, and seamless cloud integration.

## Local LLM Integration

Developers can run local large language models via **Ollama**, using open-source libraries such as:

- **OllamaSharp**: A C# client for interacting with Ollama.
- **Semantic Kernel**: Microsoft's SDK for integrating AI services into applications.

## Use Cases

This stack is particularly effective for **private knowledge workflows**, such as local markdown wikis with document ingestion and question-answering capabilities, ensuring data remains on-premise.

Enter fullscreen mode Exit fullscreen mode

These examples make the demo much more concrete and easier for readers to trust.

Why This POC Is Good

This POC is simple, but it teaches many important engineering ideas:

  • local model integration in C#
  • markdown-based AI knowledge design
  • AI-assisted ingestion workflow
  • safe structured output parsing
  • file-based knowledge management
  • query-time synthesis from curated context

It is a very good educational bridge between:

  • plain prompt engineering
  • file-based knowledge systems
  • and full RAG architectures

Limitations of This POC

Be honest with your readers. This demo is useful, but it is still a demo.

Current limitations:

  • it is console-based only
  • article selection is simple and file-based
  • there is no embedding or semantic ranking layer
  • article context size is manually bounded
  • source attribution is prompt-based, not enforced by retrieval metadata
  • large wiki collections may require a hybrid or full RAG architecture later

That is okay. Simplicity is a feature here.

How to Extend It Later

If your readers want to continue, they can add:

  • command-line arguments for custom ingestion and queries
  • ASP.NET Core Minimal API endpoints
  • Blazor UI for article management
  • stronger JSON schema validation
  • better article ranking before query
  • Semantic Kernel orchestration
  • hybrid wiki + RAG support
  • file watchers for automatic wiki refresh

A nice next-step architecture could be:

  • LLM Wiki for curated stable knowledge
  • RAG for large and dynamic long-tail knowledge

That gives the best of both worlds.

Conclusion

We built a practical LLM Wiki POC in C# using .NET 8, Ollama, OllamaSharp, markdown files, and the kimi-k2.6:cloud model.

More importantly, we learned a design lesson that is easy to forget in modern AI work:

Not every problem needs RAG first.

Sometimes, the best answer is a clean, curated, lovingly maintained wiki.

If your knowledge is small, stable, and important, a markdown-first LLM Wiki can be wonderfully effective. It is easy to understand, easy to debug, easy to version-control, and easy to teach.

Then, when your world grows larger, you can invite RAG to the party.

Happy coding, and may your markdown always stay tidy.

Love C# & AI!