# AI 提供商插件 Deft 的 AI 层遵循一切皆插件模型:提供商框架本身(`deft/stdext/ai`)对任何具体的 LLM 厂商 一无所知。每个提供商——DeepSeek、Anthropic、OpenAI、Ollama、Z.AI 或第三方提供商——都是一个 独立的包,由框架在运行时发现并加载。 ## 发现机制如何工作 1. 包在其清单中声明标签:
%Package{
    owner "deft" name "ai-deepseek" version "0.1.0"
    tags @{ "ai" "ai-provider" }
    main "src/ai-deepseek.dft" }
2. 首次 AI 调用时,`deft/stdext/ai/plugins` 扫描所有已配置的包根目录(`pkg/list`),求值每个 `package.dft`,并挑选带有 `"ai-provider"` 标签的包。 3. 每个命中的包会被挂载(`ai-<name>`)并在运行时导入。其入口模块声明 `implements AiProviderExtension`;在提供商加入注册表之前,VM 会依据契约校验导出。 缺少契约字段会导致加载明确失败。 4. `ai/refresh` 会重新扫描,从而能发现会话中途安装的提供商(已加载的模块会被复用)。 开发检出会遮蔽同名的已安装副本,重复的提供商键按先到者优先解析。通用宿主是 `deft/stdext/plugin`——未来的插件类型(工具、技能、循环等)可复用它,并带上各自的标签和契约类型。 ## 契约:`AiProviderExtension` 该契约声明于 `deft/stdext/types`,模块导出: | 字段 | 类型 | 用途 | |---|---|---| | `key` | keyword | 注册表键(`:deepseek`) | | `label` | string | 菜单显示名称 | | `version` | string | 插件版本 | | `base-url` | string | 默认 API 基础 URL | | `env-var` | string? | 保存 API 密钥的环境变量(`nil` = 无) | | `default-model` | string | cfg 未指定时使用的模型 | | `extensions` | map? | 由 `build-cfg` 合并的默认 cfg 字段(例如思考模式) | | `Provider` | any | `AiProvider` 协议实例 | ## 协议:`AiProvider` 该协议定义于 `deft/stdext/ai`,方法分为三组: - 请求构造——`models`、`url`、`headers`、`body`、 `messages-with-user`、`tool-format` - 响应解析——`extract-content`、`extract-reasoning`、 `extract-usage`、`has-tool-use`、`extract-tool-calls`、 `build-tool-results`、`finish-reason`、`scavenge-tool-calls` - 策略/能力——`context-window`、`cost`、`compact-message`, 以及可选的 `balance` / `refresh-models` 能力(桩实现返回 `nil`;消费者对它们使用 `await`,普通值会直接透传) `deft/stdext/ai` 驱动工具使用循环,`ai/budget` 根据 `context-window` 推导 token 上限,`ai/config` 从描述符构建 cfg 映射。消费者——聊天应用、编辑器的 AI 扩展、 帮助浏览器——只导入 `deft/stdext/ai/registry` 并传入 cfg。 ## 易用 API
import "deft/stdext/ai/registry" as ai

[ai/list-providers]                 # @{ :deepseek :anthropic ... }
[ai/provider-label :deepseek]       # "DeepSeek"
[ai/provider-models :ollama]        # @{ "llama3.2" ... }
[ai/tool-format :anthropic]         # :anthropic

set cfg [ai/default-cfg]            # :deepseek if installed, else first
set cfg [ai/build-cfg :openai "gpt-4o-mini" :temperature 0.2]
set reply [await [ai/ask $cfg "Explain this function."]]
## 编写提供商 复制 `packages/ai-deepseek`(本地服务器则用 `ai-ollama`),重命名包目录,然后: 1. 更新 `package.dft`:`name`、`main`、`exports`,保留 `"ai-provider"` 标签。 2. 在入口模块中 `implements AiProviderExtension`,导出契约字段,并 `defimpl YourType ai/AiProvider { ... }`。 3. 为你的模型添加 `context-window` 行、一个 `tool-format`,并在适用时添加 `cost`/`balance`/`refresh-models`。 4. 将包放入预置文件的 `:pkgs` 根目录下(或安装它)—— 框架会在下次扫描时找到它。 添加提供商永远无需修改 `deft/stdext/ai`。