用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
直接命令不会经过审查 Prompt;运行前请先检查来源。
npx skills add https://github.com/rudironsoni/Synaxis --skill dotnet-semantic-kernel命令会保持在同一行。复制前请横向滚动并检查完整内容。
想先保存到本地?可下载 SkillsMP 当前能够提供的文件。
AI-powered wiki generation for code repositories with commands, agents, and skills
Routes .NET/C# work to domain skills. Loads coding-standards for code paths.
Skill manifest management for dotnet-agent-harness. Tracks skill dependencies, conflicts, version compatibility, and provides validation and resolution tools. Triggers on: skill manifest, dependency resolution, skill compatibility, version conflicts, build manifest, validate dependencies.
基于 SOC 职业分类
正在显示 SKILL.md
| name | dotnet-semantic-kernel |
| description | Integrates AI/LLM via Semantic Kernel. Plugins, prompt templates, memory stores, agents. |
Microsoft Semantic Kernel for AI and LLM orchestration in .NET applications. Covers kernel setup and configuration, plugin/function calling, prompt templates with Handlebars and Liquid syntax, memory and vector store integration, planners, the agents framework, and integration with Azure OpenAI, OpenAI, and local models.
Cross-references: [skill:dotnet-csharp-async-patterns] for async streaming patterns used with chat completions, [skill:dotnet-csharp-dependency-injection] for kernel service registration in ASP.NET Core, [skill:dotnet-resilience] for retry policies on AI service calls, [skill:dotnet-csharp-configuration] for managing API keys and model configuration.
The Kernel is the central object in Semantic Kernel. It manages AI service connections, plugins, and function invocation.
| Package | Purpose |
|---|---|
Microsoft.SemanticKernel | Core kernel, function calling, prompt templates |
Microsoft.SemanticKernel.Connectors.AzureOpenAI | Azure OpenAI chat/embedding/image services |
Microsoft.SemanticKernel.Connectors.OpenAI | OpenAI chat/embedding/image services |
Microsoft.SemanticKernel.Connectors.Ollama | Ollama local model integration |
Microsoft.SemanticKernel.Plugins.Core | Built-in plugins (time, math, text) |
Microsoft.SemanticKernel.Agents.Core | Agent framework (chat agents, group chat) |
Microsoft.Extensions.VectorData.Abstractions | Vector store abstraction layer |
Microsoft.SemanticKernel.Connectors.Qdrant | Qdrant vector store connector |
Microsoft.SemanticKernel.Connectors.AzureAISearch | Azure AI Search vector store connector |
using Microsoft.SemanticKernel;
var builder = Kernel.CreateBuilder();
// Azure OpenAI
builder.AddAzureOpenAIChatCompletion(
deploymentName: "gpt-4o",
endpoint: Environment.GetEnvironmentVariable("AZURE_OPENAI_ENDPOINT")!,
apiKey: Environment.GetEnvironmentVariable("AZURE_OPENAI_API_KEY")!);
var kernel = builder.Build();
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddKernel();
builder.Services.AddAzureOpenAIChatCompletion(
deploymentName: builder.Configuration["AI:DeploymentName"]!,
endpoint: builder.Configuration["AI:Endpoint"]!,
apiKey: builder.Configuration["AI:ApiKey"]!);
// Register plugins
builder.Services.AddSingleton<OrderPlugin>();
builder.Services.AddSingleton(sp =>
{
var kernel = sp.GetRequiredService<Kernel>();
kernel.Plugins.AddFromObject(sp.GetRequiredService<OrderPlugin>());
return kernel;
});
Register multiple AI services and select by service ID:
var builder = Kernel.CreateBuilder();
builder.AddAzureOpenAIChatCompletion(
deploymentName: "gpt-4o",
endpoint: endpoint,
apiKey: apiKey,
serviceId: "gpt4o");
builder.AddAzureOpenAIChatCompletion(
deploymentName: "gpt-4o-mini",
endpoint: endpoint,
apiKey: apiKey,
serviceId: "gpt4o-mini");
var kernel = builder.Build();
// Select service at invocation time
var settings = new PromptExecutionSettings { ServiceId = "gpt4o-mini" };
var result = await kernel.InvokePromptAsync("Summarize: {{$input}}", new(settings)
{
["input"] = longDocument
});
#pragma warning disable SKEXP0070 // Ollama connector is experimental
var builder = Kernel.CreateBuilder();
builder.AddOllamaChatCompletion(
modelId: "llama3.2",
endpoint: new Uri("http://localhost:11434"));
var kernel = builder.Build();
Plugins expose .NET methods as functions that the AI model can invoke. This is the primary mechanism for grounding LLM responses in real data and actions.
using Microsoft.SemanticKernel;
using System.ComponentModel;
public sealed class OrderPlugin
{
private readonly IOrderRepository _repository;
public OrderPlugin(IOrderRepository repository) => _repository = repository;
[KernelFunction("get_order")]
[Description("Retrieves an order by its ID")]
public async Task<OrderSummary?> GetOrderAsync(
[Description("The unique order identifier")] string orderId,
CancellationToken ct = default)
{
var order = await _repository.GetByIdAsync(orderId, ct);
return order is null ? null : new OrderSummary(order);
}
[KernelFunction("list_recent_orders")]
[Description("Lists the most recent orders for a customer")]
public async Task<IReadOnlyList<OrderSummary>> ListRecentOrdersAsync(
[Description("The customer ID")] string customerId,
[Description("Maximum number of orders to return")] int limit = 10,
CancellationToken ct = default)
{
var orders = await _repository.GetRecentAsync(customerId, limit, ct);
orders.Select(o => OrderSummary(o)).ToList();
}
}
var kernel = builder.Build();
// From an object instance (DI-friendly)
kernel.Plugins.AddFromObject(new OrderPlugin(orderRepo), "Orders");
// From a type (kernel creates the instance)
kernel.Plugins.AddFromType<TimePlugin>("Time");
// From functions directly
kernel.Plugins.AddFromFunctions("Math",
[
KernelFunctionFactory.CreateFromMethod(
([Description("First number")] double a, [Description("Second number")] double b) => a + b,
"Add",
"Adds two numbers")
]);
Enable the model to call functions automatically during chat:
var settings = new AzureOpenAIPromptExecutionSettings
{
FunctionChoiceBehavior = FunctionChoiceBehavior.Auto()
};
var chatHistory = new ChatHistory();
chatHistory.AddUserMessage("What's the status of order ORD-12345?");
var result = await kernel.GetRequiredService<IChatCompletionService>()
.GetChatMessageContentAsync(chatHistory, settings, kernel);
// The model calls get_order("ORD-12345") automatically and responds with the result
Console.WriteLine(result.Content);
Intercept function calls for logging, authorization, or modification:
public sealed class AuthorizationFilter : IFunctionInvocationFilter
{
public async Task OnFunctionInvocationAsync(
FunctionInvocationContext context,
Func<FunctionInvocationContext, Task> next)
{
// Check authorization before function execution
if (context.Function.Name == "get_order")
{
var orderId = context.Arguments["orderId"]?.ToString();
// Validate access...
}
await next(context);
// Post-execution: log or modify result
}
}
// Register the filter
builder.Services.AddSingleton<IFunctionInvocationFilter, AuthorizationFilter>();
Prompt templates support variable substitution and function calling within structured prompts.
var result = await kernel.InvokePromptAsync(
"Summarize the following text in {{$style}} style:\n\n{{$input}}",
new KernelArguments
{
["input"] = articleText,
["style"] = "concise bullet points"
});
Handlebars templates support conditionals, loops, and function calls:
var templateString = """
<message role="system">
You are a helpful customer service agent.
{{#if isVip}}You are speaking with a VIP customer. Be extra attentive.{{/if}}
</message>
<message role="user">
Customer: {{customerName}}
Query: {{query}}
Recent orders:
{{#each orders}}
- Order {{this.Id}}: {{this.Status}} ({{this.Date}})
{{/each}}
</message>
""";
var factory = new HandlebarsPromptTemplateFactory();
var template = factory.Create(new PromptTemplateConfig(templateString)
{
TemplateFormat = HandlebarsPromptTemplateFactory.HandlebarsTemplateFormat
});
var result = await template.RenderAsync(kernel, new KernelArguments
{
["customerName"] = "Alice",
["query"] = "Where is my order?",
["isVip"] = true,
["orders"] = recentOrders
});
Define prompts as YAML files for separation of concerns:
# prompts/summarize.yaml
name: Summarize
description: Summarizes text to a specified length
template_format: handlebars
template: |
<message role="system">
Summarize the following text in approximately {{maxWords}} words.
Focus on key facts and actionable items.
</message>
<message role="user">{{input}}</message>
input_variables:
- name: input
description: The text to summarize
is_required: true
- name: maxWords
description: Target word count
default: "100"
execution_settings:
default:
temperature: 0.3
max_tokens: 500
var yamlContent = File.ReadAllText("prompts/summarize.yaml");
var function = kernel.CreateFunctionFromPromptYaml(yamlContent);
var result = await kernel.InvokeAsync(function, new KernelArguments
{
["input"] = longText,
["maxWords"] = "50"
});
Semantic Kernel provides abstractions for vector storage, enabling retrieval-augmented generation (RAG) patterns.
using Microsoft.Extensions.VectorData;
public sealed class DocumentRecord
{
[VectorStoreRecordKey]
public string Id { get; set; } = string.Empty;
[VectorStoreRecordData(IsFilterable = true)]
public string Source { get; set; } = string.Empty;
[VectorStoreRecordData(IsFullTextSearchable = true)]
public string Content { get; set; } = string.Empty;
[VectorStoreRecordVector(Dimensions: 1536)]
public ReadOnlyMemory<float> Embedding { get; set; }
}
using Microsoft.SemanticKernel.Connectors.Qdrant;
var builder = Kernel.CreateBuilder();
// Register embedding generation
builder.AddAzureOpenAITextEmbeddingGeneration(
deploymentName: "text-embedding-3-small",
endpoint: endpoint,
apiKey: apiKey);
// Register vector store
builder.Services.AddQdrantVectorStore("localhost", 6334);
public sealed class RagService
{
private readonly IVectorStoreRecordCollection<string, DocumentRecord> _collection;
private readonly ITextEmbeddingGenerationService _embeddingService;
private readonly IChatCompletionService _chatService;
public RagService(
IVectorStore vectorStore,
ITextEmbeddingGenerationService embeddingService,
IChatCompletionService chatService)
{
_collection = vectorStore.GetCollection<string, DocumentRecord>("documents");
_embeddingService = embeddingService;
_chatService = chatService;
}
public async Task<string> AskAsync(string question, CancellationToken ct = default)
{
// 1. Generate embedding for the question
var questionEmbedding = await _embeddingService
.GenerateEmbeddingAsync(question, cancellationToken: ct);
// 2. Search for relevant documents
var searchResults = _collection.VectorizedSearchAsync(
questionEmbedding,
new VectorSearchOptions { Top = 5 },
ct);
// 3. Build context from search results
var contextBuilder = new StringBuilder();
await foreach (var result in searchResults)
{
contextBuilder.AppendLine(result.Record.Content);
contextBuilder.AppendLine();
}
chatHistory = ChatHistory();
chatHistory.AddSystemMessage(
);
chatHistory.AddUserMessage(question);
response = _chatService
.GetChatMessageContentAsync(chatHistory, cancellationToken: ct);
response.Content ?? .Empty;
}
}
public async Task IngestAsync(
string documentId,
string content,
string source,
CancellationToken ct = default)
{
await _collection.CreateCollectionIfNotExistsAsync(ct);
var embedding = await _embeddingService
.GenerateEmbeddingAsync(content, cancellationToken: ct);
await _collection.UpsertAsync(new DocumentRecord
{
Id = documentId,
Content = content,
Source = source,
Embedding = embedding
}, cancellationToken: ct);
}
The Semantic Kernel agents framework enables building multi-agent systems where specialized agents collaborate on tasks.
#pragma warning disable SKEXP0110 // Agents framework is experimental
using Microsoft.SemanticKernel.Agents;
var agent = new ChatCompletionAgent
{
Name = "OrderAssistant",
Instructions = """
You are an order management assistant. Help customers check order status,
process returns, and answer questions about their orders.
Always verify the customer's identity before sharing order details.
""",
Kernel = kernel,
Arguments = new KernelArguments(new AzureOpenAIPromptExecutionSettings
{
FunctionChoiceBehavior = FunctionChoiceBehavior.Auto()
})
};
// Invoke via a thread (required -- agents do not accept bare strings)
var thread = new ChatHistoryAgentThread();
await foreach (var message in agent.InvokeAsync(
"What's the status of my order ORD-12345?", thread))
{
Console.WriteLine(message.Content);
}
Multiple agents can collaborate in a group chat with termination conditions:
var analyst = new ChatCompletionAgent
{
Name = "DataAnalyst",
Instructions = "You analyze data and provide insights. Present findings clearly.",
Kernel = kernel
};
var writer = new ChatCompletionAgent
{
Name = "ReportWriter",
Instructions = "You take analytical findings and write clear, actionable reports.",
Kernel = kernel
};
var chat = new AgentGroupChat(analyst, writer)
{
ExecutionSettings = new AgentGroupChatSettings
{
TerminationStrategy = new ApprovalTerminationStrategy
{
MaximumIterations = 6
}
}
};
chat.AddChatMessage(
new ChatMessageContent(AuthorRole.User, "Analyze Q4 sales trends and write a summary report."));
await foreach (var message in chat.InvokeAsync())
{
Console.WriteLine($"[{message.AuthorName}]: {message.Content}");
}
For stateful conversations with built-in tools (code interpreter, file search):
#pragma warning disable SKEXP0110
// Create the assistant via the builder pattern
OpenAIAssistantAgent agent = await OpenAIAssistantAgent.CreateAsync(
kernel,
new OpenAIAssistantDefinition("gpt-4o")
{
Name = "DataProcessor",
Instructions = "You process CSV data and generate insights.",
EnableCodeInterpreter = true
});
try
{
// Assistant agents use threads for stateful conversations
var thread = await agent.CreateThreadAsync();
await foreach (var message in agent.InvokeAsync(
"Analyze the attached sales data.", thread))
{
Console.WriteLine(message.Content);
}
}
finally
{
await agent.DeleteAsync();
}
Note: The agents framework is experimental (SKEXP0110). APIs change frequently between Semantic Kernel releases. Verify method signatures against the latest samples when adopting.
For chat applications, stream responses token-by-token:
var chatService = kernel.GetRequiredService<IChatCompletionService>();
var chatHistory = new ChatHistory("You are a helpful assistant.");
chatHistory.AddUserMessage(userInput);
var settings = new AzureOpenAIPromptExecutionSettings
{
FunctionChoiceBehavior = FunctionChoiceBehavior.Auto()
};
await foreach (var chunk in chatService.GetStreamingChatMessageContentsAsync(
chatHistory, settings, kernel))
{
Console.Write(chunk.Content);
}
[Description] attributes on functions and parameters so the model knows when and how to call themIVectorStore to allow switching between Qdrant, Azure AI Search, and other providersSKEXP* warnings per-call, not globally, so you notice when APIs graduate to stablebuilder.Configuration or environment variables. Hardcoded secrets leak into source control and prevent environment-specific configuration.SKEXP* warnings globally -- experimental APIs change frequently. Suppress per-usage (#pragma warning disable SKEXP0110) so new experimental usage sites are flagged by the compiler.Kernel instance per request in ASP.NET Core -- register the kernel in DI as a singleton (it is thread-safe) and clone with kernel.Clone() if per-request state is needed.CancellationToken in plugin functions -- AI function calls can be cancelled by the user or timeout policies. Always propagate CancellationToken through plugin method signatures.AddAzureOpenAIChatCompletion and AddOpenAIChatCompletion without serviceId -- without a service ID, the last registration wins. Use explicit serviceId when registering multiple AI services.Microsoft.SemanticKernel NuGet package (1.x stable)