必须先注册 ichatcompletionservice 才能调用 invokepromptasync,否则抛出“no chat completion service registered”异常;推荐用 kernel.createbuilder().addopenaichatcompletion() 等方式显式注册并 build() 后使用。

直接能跑通的最小可行路径就两条:用 InvokePromptAsync 快速验证连接,或用 Kernel.CreateBuilder() 注册服务后调用语义函数。别一上来就搞插件、RAG 或 Planner,90% 的失败都卡在初始化和依赖注入这一步。
为什么 kernel.InvokePromptAsync 会抛出 No chat completion service registered
这是最常踩的坑——InvokePromptAsync 看似“免配置”,其实底层仍依赖已注册的 IChatCompletionService。没注册就调用,必然炸。
- 必须显式添加服务,比如
.AddOpenAIChatCompletion("gpt-4o", apiKey)或.AddAzureOpenAIChatCompletion(...) - 如果用 Ollama,得装
Microsoft.SemanticKernel.Connectors.Ollama包,并调用.AddOllamaChatCompletion("qwen3:1.7b", "http://localhost:11434") -
Kernel.CreateBuilder()构建完必须调.Build(),漏掉这步kernel是 null 引用 - 环境变量读取别写错名,
Environment.GetEnvironmentVariable("OPENAI_API_KEY")比硬编码更安全,也方便切换环境
InvokePromptAsync 和 CreateSemanticFunction 的本质区别
前者是直连 LLM 的快捷通道,后者才是 SK 的核心抽象:把 prompt 变成可描述、可编排、可复用的“函数”。
-
InvokePromptAsync("你好"):不走函数注册表,不解析变量,不支持{{input}}或命名参数,纯字符串透传 -
CreateSemanticFunction必须带description字符串,否则 Planner 无法理解用途;模板里用{{input}}接主输入,{{topic}}接命名参数,调用时传new() { ["topic"] = "C#" } - 返回值统一是
FunctionResult,取内容必须显式.GetValue<string>()</string>,不是直接.ToString() - 语义函数内部仍是 HTTP 调用,不是本地 C# 方法,所以不能传对象、不能有副作用、不能 throw 异常来中断流程
Ollama 本地模型对接时的三个硬性条件
Ollama 不是“装完就能用”,它和 SK 的协作有明确前提,缺一不可。
- Ollama 进程必须在后台运行:
ollama serve,不能只靠ollama run临时启动 - 模型必须已拉取:
ollama pull qwen3:1.7b,SK 不会自动下载,找不到模型会报model not found - 连接器版本要匹配:SK v1.0+ 才内置
OllamaChatCompletionService,老项目升级时注意 NuGet 包是否含Microsoft.SemanticKernel.Connectors.Ollama - 端口默认是
http://localhost:11434,若改过配置(比如 Docker 映射),必须同步更新AddOllamaChatCompletion的 baseUri 参数
最容易被忽略的是:所有服务注册(OpenAI/Azure/Ollama)都必须在 Kernel.CreateBuilder() 链式调用中完成,不能 build 之后再 try-add。一旦 kernel 实例化,服务容器就冻结了。











