一键导入
koan-ai-integration
Chat endpoints, embeddings, RAG workflows, vector search
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
菜单
Chat endpoints, embeddings, RAG workflows, vector search
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
基于 SOC 职业分类
Auto-registration via KoanAutoRegistrar, minimal Program.cs, "Reference = Intent" pattern
Aggregate boundaries, relationships, lifecycle hooks, value objects
Entity<T> patterns, GUID v7 auto-generation, static methods vs manual repositories
Transparent L1/L2 caching for Entity<T>, [Cacheable] attribute, cross-node coherence, per-request opt-out
Run a mandatory pre-implementation exploration workflow before writing production code in Koan (.NET/C#). Use when a task requires code changes and Codex must first map concerns/layers, read relevant files and docs, check existing constants and types, identify the closest existing pattern, plan exact code placement, and confirm architectural guardrails.
EntityController<T>, custom routes, payload transformers, auth policies
| name | koan-ai-integration |
| description | Chat endpoints, embeddings, RAG workflows, vector search |
AI capabilities integrate seamlessly with entity patterns. Store embeddings on entities, use vector repositories for search, and leverage standard Entity patterns for AI-enriched data.
The AI facade is the static Client class — no DI injection needed. It resolves the configured
pipeline automatically. For controller use, call Client.ChatAsync() directly.
public class ChatController : ControllerBase
{
[HttpPost]
public async Task<IActionResult> Chat(
[FromBody] ChatRequest request,
CancellationToken ct)
{
var response = await Client.ChatAsync(request.Message, ct);
return Ok(new { message = response.Content, usage = response.Usage });
}
// Streaming — use Server-Sent Events or chunked response
[HttpPost("stream")]
public async IAsyncEnumerable<string> Stream(
[FromBody] ChatRequest request,
[EnumeratorCancellation] CancellationToken ct)
{
await foreach (var chunk in Client.StreamAsync(request.Message, ct))
yield return chunk.Content;
}
}
When you need to inject the pipeline (e.g., for testability), inject IAiPipeline and call
PromptAsync / StreamAsync directly:
public class SummaryService(IAiPipeline ai)
{
public Task<AiChatResponse> Summarise(string text, CancellationToken ct) =>
ai.PromptAsync(new AiChatRequest
{
SystemPrompt = "Summarise the following text concisely.",
Messages = [new AiMessage { Role = "user", Content = text }]
}, ct);
}
There is no
IAiinterface and noChatAsyncmethod on any injectable type. Use the staticClientclass for the default pipeline, or injectIAiPipelinewhen you need a testable seam.
[DataAdapter("weaviate")] // Force vector database
public class ProductSearch : Entity<ProductSearch>
{
public string ProductId { get; set; } = "";
public string Description { get; set; } = "";
[VectorField]
public float[] DescriptionEmbedding { get; set; } = Array.Empty<float>();
// Semantic search
public static async Task<List<ProductSearch>> SimilarTo(
string query,
CancellationToken ct = default)
{
return await Vector<ProductSearch>.SearchAsync(query, limit: 10, ct);
}
}
public class KnowledgeBaseService
{
public async Task<string> AnswerQuestion(string question, CancellationToken ct)
{
// 1. Find relevant documents via vector search
var relevantDocs = await KnowledgeDocument.SimilarTo(question, ct);
// 2. Build context from documents
var context = string.Join("\n\n", relevantDocs.Select(d => d.Content));
// 3. Query AI with context — use the fluent conversation builder
var response = await Client.Converse()
.WithSystem($"Answer based on this context:\n\n{context}")
.WithUser(question)
.PromptAsync(ct);
return response.Content;
}
}
{
"Koan": {
"AI": {
"Providers": {
"Primary": {
"Type": "OpenAI",
"ApiKey": "{OPENAI_API_KEY}",
"Model": "gpt-4"
},
"Fallback": {
"Type": "Ollama",
"BaseUrl": "http://localhost:11434",
"Model": "llama2"
}
}
},
"Data": {
"Sources": {
"Vectors": {
"Adapter": "weaviate",
"ConnectionString": "http://localhost:8080"
}
}
}
}
}
The AI subsystem routes operations by category (Chat, Embed, Ocr) with independent source/model configuration:
{
"Koan": {
"Ai": {
"Chat": { "Source": "ollama-gpu", "Model": "llama3" },
"Embed": { "Source": "openai-prod", "Model": "text-embedding-3-small" },
"Ocr": { "Via": "Chat", "Model": "glm-ocr" }
}
}
}
Override routing per-operation:
using (Client.Scope(chat: "fast-local", embed: "cloud-prod"))
{
var answer = await Client.Chat("Summarize this", ct);
var vector = await Client.Embed("search text", ct);
}
EntityAi in Koan.Data.AI bridges entities with AI operations using convention inference:
// Embed entity content (convention: all string properties)
float[] vector = await EntityAi.Embed(myNote, ct);
// Chat with entity as context (injected as system prompt)
string answer = await EntityAi.Chat("What are the key points?", myNote, ct);
// OCR from entity's byte[] property
string text = await EntityAi.Ocr(myDocument, ct);
// Extract text without AI call
string content = EntityAi.ExtractText(myNote);
Convention chain: [Embedding] attribute → AllStrings policy → JSON fallback.
Named recipes bind capabilities to models. ML engineers author recipes, developers select them:
{
"Koan": {
"Ai": {
"ActiveRecipe": "fast-local",
"Recipes": {
"fast-local": { "Chat": "phi3:mini", "Embed": "nomic-embed-text" },
"cloud-prod": { "Chat": "gpt-4o", "Embed": "text-embedding-3-large" }
}
}
}
}
Recipes are sparse — missing keys mean "no opinion" (falls through to advisor/config).
Automatic AI processing for media entities on upload/save:
[MediaAnalysis(Analysis = MediaAnalysis.Describe | MediaAnalysis.Ocr, Async = true)]
[Embedding]
public class PhotoAsset : MediaEntity<PhotoAsset>
{
public string? AiDescription { get; set; } // Auto-populated by Describe
public string? OcrText { get; set; } // Auto-populated by Ocr
public float[]? Embedding { get; set; } // Auto-populated by [Embedding]
}
Pipeline: Upload → Store → [MediaAnalysis] → [Embedding] → Save atomically.
Analysis modes (combinable via flags):
Convention-detected property mapping: AiDescription, OcrText, Transcript, Category. Override with explicit property names in the attribute.
Cross-modal search: analysis results automatically feed into [Embedding] text via MediaAnalysisEmbeddingBridge.
docs/guides/ai-integration.mddocs/guides/ai-vector-howto.mddocs/decisions/AI-0021-category-driven-ai-with-convention-defaults.md (Category-driven AI)docs/decisions/AI-0032-intent-capability-resolution-with-recipes.md (Recipes)samples/S5.Recs/ (AI recommendation engine)docs/decisions/AI-0027-media-analysis-attribute.md (Media Analysis Attribute)samples/S16.PantryPal/ (Vision AI integration)