关于 Decidealot
Decidealot 通过兼容 TypeSafe 的 HTTP API 提供本地 Laya、Von、CLM 模型或托管 Jev。应用和 Agent 可获取带概率的类型化决策,具体行动仍由调用方控制。
主要功能
- 01返回类型化 choice、score 和 noul 答案
- 02支持本地 Laya、Von 和 CLM 模型
- 03通过 TypeSafe 使用托管 Jev
- 04提供 HTTP 与 MCP Streamable HTTP 接口
- 05批量提交决策请求
- 06加载和卸载模型提供方
适用场景
- 01将策略决策路由至人工审核
- 02比较支持模型给出的决策结果
- 03批量提交相互独立的决策
- 04让 MCP 客户端检查答案及其概率
MCP 相关
在 `/mcp` 提供 MCP Streamable HTTP,包含决策、批处理、模型列表和卸载本地模型等工具。MCP 工具返回与 HTTP 响应对应的结构化结果。
配置
本地服务的配置在各客户端中通用,复制后粘贴到客户端的 MCP 配置文件即可。
工具
本地服务需要在你的电脑上运行后才能读取工具,维护者暂未提供工具列表。
详细介绍
Decidealot
使用你的硬件或 TypeSafe 托管的 Jev。通过一个兼容 TypeSafe 的 HTTP 和 MCP 端点运行 Laya、Von、CLM 投影头或 Jev。
启动时,Decidealot 会下载并验证所有已启用的本地模型包。之后,它只会加载请求所选的提供方,在配置的空闲时间过后卸载该提供方,并返回带有模型概率的类型化 choice、score 和 noul 答案。CLM 会在一个已配置的 Qwen3-8B embeddings 端点上添加一个小型本地投影头。它通过同一个本地容器提供 TypeSafe HTTP API 和 MCP Streamable HTTP。
目录
快速开始
你需要 Docker。此命令会在回环地址上启动 CPU 镜像,将下载的模型文件存储在一个范围严格受限的主机目录中,并且不给容器任何能力或可写的根文件系统。
model_directory="$HOME/.local/share/decidealot/models"
runtime_uid=$(id -u)
runtime_gid=$(id -g)
mkdir --parents "$model_directory"
docker run --detach --name decidealot --init --restart unless-stopped \
--user "$runtime_uid:$runtime_gid" \
--read-only --cap-drop ALL --security-opt no-new-privileges:true \
--pids-limit 512 --memory 8g --cpus 4 \
--tmpfs /tmp:rw,noexec,nosuid,size=128m \
--tmpfs /var/run:rw,noexec,nosuid,size=8m \
--log-driver json-file --log-opt max-size=10m --log-opt max-file=5 \
--mount type=bind,source="$model_directory",target=/models \
--publish 127.0.0.1:8080:8080 \
psyb0t/decidealot:latest
检查服务,然后让 Laya 做出一个类型化决策:
curl --fail http://127.0.0.1:8080/health
curl --fail http://127.0.0.1:8080/v1/systemone \
--header 'Content-Type: application/json' \
--data '{
"model": "laya",
"state": "A proposed action would permanently delete protected data.",
"questions": {
"handling": {
"type": "choice",
"instructions": "Choose the required handling for this action.",
"criteria": {
"allow": "The action is reversible and does not affect protected data.",
"require_review": "The action is irreversible or affects protected data."
}
}
}
}'
首次启动服务时会下载已启用并固定版本的模型包,可能需要几分钟。默认配置会启用 Laya 和 Von。发送决策前,请等待 /health 就绪。之后启动服务时会复用相同的主机目录。
以下是一个示例响应。答案、概率和 token 数量会随模型调用而变化:
{
"model": "laya",
"answers": {
"handling": {
"type": "choice",
"choice": "require_review",
"confidence": 0.94,
"probabilities": {"allow": 0.06, "require_review": 0.94}
}
},
"usage": {"input_tokens": 91, "output_tokens": 0}
}
对于这个结果,你的应用会将操作加入队列,等待人工审核,而不是执行该操作。Decidealot 不会执行操作。调用方会检查所选标签并应用自己的概率阈值,例如仅当 choice 为 allow 且 probabilities.allow 至少为 0.95 时才允许执行操作。
使用托管 Jev
在私有环境文件或密钥存储中设置 DECIDEALOT_TYPESAFE_API_KEY。存在该密钥时,Jev 会自动启用。调用 GET /v1/models,并选择 TypeSafe 返回的托管名称,例如 jev-latest。Decidealot 会缓存经过身份验证的 TypeSafe 模型目录 60 秒,并在缓存过期后收到下一次模型列表请求或托管模型请求时刷新。新的托管模型名称无需发布 Decidealot 新版本。它会将完整的 state 和 questions 发送到 TypeSafe 固定的 HTTPS API,而非本地模型。密钥绝不能放在请求正文、受版本控制的文件或客户端应用中。
若要运行仅包含 Jev 的容器,请禁用所有本地模型,这样启动时就不会下载任何模型包。从密钥存储中通过环境变量传入上游密钥,然后使用下方展示的相同 REST 或 MCP 端点:
docker run --detach --name decidealot --init --restart unless-stopped \
--read-only --cap-drop ALL --security-opt no-new-privileges:true \
--tmpfs /tmp:rw,noexec,nosuid,size=128m \
--env DECIDEALOT_TYPESAFE_API_KEY \
--env DECIDEALOT_LAYA_ENABLED=false \
--env DECIDEALOT_VON_ENABLED=false \
--publish 127.0.0.1:8080:8080 \
psyb0t/decidealot:latest
该变量必须已在 shell 中设置,或由容器管理器提供。GET /v1/models 可确认已启用哪些 Jev 选择器。API 指南提供完整的请求与响应示例。TypeSafe 会对其 API 调用收费;模型概率仍需使用你自己的操作阈值。
使用 API
将状态和有界问题发送给 judge。Decidealot 会返回带概率的类型化结果。
| Endpoint | 作用 |
|---|---|
POST /v1/systemone | 针对 state 运行所选的本地模型或托管 Jev,并返回类型化答案。 |
POST /v1/systemone/batch | 运行相互独立的 System One 请求,并返回有序的 results 列表。 |
GET /v1/models | 列出所有受支持的别名及其对应的模型。 |
POST /v1/models/unload | 停止已加载的本地提供方;托管 Jev 不受影响。 |
/mcp | MCP Streamable HTTP,包含 system_one、system_one_batch、list_models 和 unload_models 工具。 |
GET /health | 报告已配置的本地模型包是否就绪。仅启动 Jev 时不会下载模型包。 |
choice 问题需要命名的 criteria。score 问题需要有序的 criteria 数组,其位置即为分数。noul 问题会返回介于 0 和 1 之间的概率。API 指南介绍了请求规则、响应结构、验证失败、别名、身份验证和生命周期行为。
将主题放在 state 中,将问题和决策规则放在每个问题的 instructions 中,并在 criteria 中提供明确的描述。像 review 这样的标签并未说明应审查什么。对于 noul,请在 instructions 中写明你想获取其概率的陈述。
CLM 接受可选的扁平请求配置。所选的 model 已确定适用哪些设置:
{
"model": "clm",
"config": {"temperature": 0.8},
"state": "The operation permanently removes protected data.",
"questions": {
"review": {
"type": "noul",
"instructions": "This operation requires human review because it removes protected data."
}
}
}
CLM 的 temperature 默认为 1,接受大于 0 且小于或等于 100 的有限数值。较低的值会使其概率分布更加集中,但不会让答案更正确。Laya、Von 和托管 Jev 目前仅接受省略或为空的 config。不受支持的键和值会返回 422,绝不会被静默忽略。同样的 config 应放在 MCP 工具参数中,或每个独立的批量请求中。请求配置介绍了相关约定。
使用 MCP
同一容器会在 http://127.0.0.1:8080/mcp 提供 MCP Streamable HTTP。system_one 工具接受与 POST /v1/systemone 相同的 model、state 和 questions 字段。system_one_batch 接受一个 requests 列表,其中每一项都包含这些相同的字段。list_models 会返回实时目录。unload_models 会释放本地模型占用的内存。直接使用回环地址的客户端,以及使用 decidealot Docker 服务名称的容器,默认均可正常工作。
将 MCP 客户端指向该确切 URL。其配置格式各不相同,但连接值始终等同于以下内容:
{
"mcpServers": {
"decidealot": {
"url": "http://127.0.0.1:8080/mcp",
"headers": {
"Authorization": "Bearer your-token-here"
}
}
}
}
仅当 DECIDEALOT_API_KEY 为空时,才省略 Authorization 标头。MCP 工具会返回与 HTTP 响应正文相匹配的结构化输出,因此 Agent 可以先检查概率,再选择下一步操作。仅支持本地 stdio 的客户端可以使用Agent 集成中介绍的可选 OpenClaw 桥接程序。API 指南介绍了工具输入、输出结构、会话行为和失败行为。
通过代理公开 MCP
MCP 服务会保持启用 DNS 重绑定保护。必须明确允许代理、隧道或公共 DNS 名称。将确切的公共 Host 值添加到 DECIDEALOT_MCP_ALLOWED_HOSTS。基于浏览器的 MCP 客户端还必须将确切来源(包括 scheme)添加到 DECIDEALOT_MCP_ALLOWED_ORIGINS。
对于发布 https://mcp.example.net/mcp 的代理,请在运行 docker compose up -d 前将以下值写入 Compose .env 文件,或通过 docker run --env 传入相同的变量:
DECIDEALOT_API_KEY=replace-with-a-real-secret
DECIDEALOT_MCP_ALLOWED_HOSTS=127.0.0.1,127.0.0.1:*,localhost,localhost:*,[::1],[::1]:*,decidealot,decidealot:*,mcp.example.net
DECIDEALOT_MCP_ALLOWED_ORIGINS=http://127.0.0.1:*,http://localhost:*,http://[::1]:*,https://mcp.example.net
当本地反向代理负责终止 TLS 时,请保留 --publish 127.0.0.1:8080:8080。代理会原样转发请求,并带上 Host: mcp.example.net。通过 bearer 身份验证后,Decidealot 会对不受信任的主机返回 421,对不受信任的浏览器来源返回 403。无效或缺失的 bearer 凭据会优先返回 401。不要禁用此保护,也不要为面向互联网的端点允许宽泛的通配符。
选择模型
每个请求都必须指定一个选择器。GET /v1/models 会在运行时返回相同的目录。
| 选择器 | 运行内容 | 适用情况 |
|---|---|---|
laya、laya-auto、laya-latest | Laya,带自动检查点路由。 | 状态可能以多种语言或文字形式提供。 |
laya-english | Laya 的英文检查点。 | 状态为英语,且使用拉丁文字。 |
laya-multilingual | Laya 的多语言检查点。 | 状态使用其他语言或文字,包括无法明确判断为英语的简短拉丁文字文本。 |
laya-typed-decisions | Laya 的检查点,针对结构化工作流决策进行了调优。 | 你的工作负载类似于重复的策略、路由、分诊或审批决策。请先用自己的案例进行验证。 |
von、von-latest、von-1.1、von-1.1.0 | 本地的纯英文 Von 1.1 模型。 | 你想获取 Von 对简短且定义明确的决策给出的独立结果,或想在标准化工作流前将其与 Laya 进行比较。 |
clm、clm-latest、clm-0.1、clm-0.1-8b | 基于一个已配置的 Qwen3-8B 嵌入端点的本地 CLM v0.1 投影头。 | 你有可信的嵌入服务,能够输出与 CLM 兼容的 4096 维 Qwen3-8B 最后一个 token 向量。 |
TypeSafe 返回的名称,例如 jev-latest | TypeSafe 托管的 Jev API。 | 你有 TypeSafe API 密钥,并且打算将状态和问题发送给 TypeSafe。 |
差异
Laya 是包含三个检查点的模型系列。它的自动选择器会根据输入文字和语言启发式规则,在英文或多语言检查点之间进行选择。对于已知的非英文短拉丁字母文本消息,请使用 laya-multilingual。laya-typed-decisions 针对重复的结构化决策任务。
Von 是独立的纯英文决策模型,适用于标准明确的简短问题。CLM 是一个本地 75 MB 投影头,而不是文本编码器。它会调用一个配置好的、兼容 OpenAI 的 /v1/embeddings URL,并要求其配置的模型返回 Qwen3-8B 最后一个 token 的向量,且恰好包含 4096 个浮点值。所有提供程序都使用相同的 TypeSafe state 和 questions 结构,并返回带概率的类型化 choice、score 和 noul 答案。应用程序会应用后续的阈值和操作。
默认情况下,Decidealot 会让一个本地提供程序常驻。只有在主机拥有足够的 RAM 或 VRAM 来容纳相应数量的进程时,才设置 DECIDEALOT_MAX_RESIDENT_LOCAL_PROVIDERS=2 或 3。一个批次可以指定超过常驻限制数量的本地模型系列;这些调用会等待可用槽位,并在需要时切换模型。对同一个底层模型的重复请求会依次运行。即使有多个常驻槽位,本地 CUDA 模型也会依次运行。默认情况下,CLM 及其 Qwen 嵌入调用会与本地串行通道共用,即使在 CPU 上也是如此。只有在此工作负载能够与其他本地模型安全并行时(例如 Qwen 在另一台机器上运行),才设置 DECIDEALOT_CLM_PARALLEL_WITH_LOCAL_MODELS=true。托管式 Jev 可以与本地任务并行。Jev 调用使用 HTTPS,不会加载、切换或卸载本地提供程序。
设置 DECIDEALOT_PROVIDER_IDLE_UNLOAD_SECONDS,选择空闲提供程序释放其模型和 Torch 内存的时间。
配置
通过 --env-file 或容器管理器传入配置。此镜像使用固定的内部端口。Docker 端口发布设置服务的可访问地址。
| 变量 | 默认值 | 含义 |
|---|---|---|
DECIDEALOT_API_KEY | 空 | 可选的 Bearer 令牌,适用于所有公开 API 和 MCP 请求。 |
DECIDEALOT_MAX_REQUEST_BYTES | 1048576 | JSON 请求正文的最大大小。 |
DECIDEALOT_MAX_BATCH_REQUESTS | 0 | 可选的批处理项目数量上限。0 表示不限制项目数量;正文大小限制仍然适用。 |
DECIDEALOT_MAX_BATCH_CONCURRENCY | 0 | 可选的并发批处理提供方调用上限。0 表示仅受模型和设备调度限制。 |
DECIDEALOT_PROVIDER_IDLE_UNLOAD_SECONDS | 600 | 自动卸载前的空闲时间。设为 0 仅禁用基于超时的卸载。 |
DECIDEALOT_MAX_RESIDENT_LOCAL_PROVIDERS | 1 | 常驻本地提供方进程的最大数量,范围为 1 至 3。无论此设置如何,CUDA 推理都会串行执行。 |
DECIDEALOT_LAYA_ENABLED | true | 下载并公开 Laya 选择器。 |
DECIDEALOT_VON_ENABLED | true | 下载并公开 Von 选择器。 |
DECIDEALOT_CLM_ENABLED | auto | 设置 embeddings URL 后启用 CLM。设为 true 可强制启用,设为 false 可跳过。 |
DECIDEALOT_CLM_EMBEDDINGS_URL | 空 | 仅供 CLM 使用的精确 OpenAI 兼容 /v1/embeddings URL。启用 CLM 时必填。 |
DECIDEALOT_CLM_EMBEDDINGS_MODEL | qwen3-8b | 发送至 embeddings 端点的模型选择器。该模型必须生成宽度为 4096 的 Qwen3-8B 最后一个 token 向量。 |
DECIDEALOT_CLM_EMBEDDINGS_API_KEY | 空 | 发送至已配置 CLM embeddings 端点的可选 Bearer 令牌。 |
DECIDEALOT_CLM_EMBEDDINGS_TIMEOUT_SECONDS | 120 | 单次 CLM embeddings 请求的超时时间(秒)。 |
DECIDEALOT_CLM_CANDIDATE_CACHE_ENTRIES | 1024 | 候选项嵌入 LRU 缓存容量,范围为 0 至 4096。0 表示禁用缓存。 |
DECIDEALOT_CLM_CANDIDATE_CACHE_TTL_SECONDS | 600 | 候选项向量的有效期,必须大于 0 且不超过 86400 秒。 |
DECIDEALOT_CLM_MAX_TEXT_BYTES | 8192 | 每个渲染后的状态加指令或候选项的 UTF-8 字节数上限,范围为 1 至 1048576。超出上限的 CLM 输入会返回 422。 |
DECIDEALOT_CLM_PARALLEL_WITH_LOCAL_MODELS | false | 允许 CLM 及其 Qwen 编码器与其他本地模型并行运行。如果它们共用此主机的资源,请保持为 false。 |
DECIDEALOT_TYPESAFE_API_KEY | 空 | 用于 TypeSafe 托管 Jev API 的私有上游 Bearer 密钥。此密钥与面向调用方的 DECIDEALOT_API_KEY 分开。 |
DECIDEALOT_JEV_ENABLED | auto | 设置上游密钥后启用 Jev。true 表示必须提供密钥;false 表示即使有密钥也隐藏 Jev。 |
DECIDEALOT_MCP_ALLOWED_HOSTS | 回环名称和 decidealot | MCP 接受的逗号分隔 Host 值。请在此添加每个反向代理主机名。 |
DECIDEALOT_MCP_ALLOWED_ORIGINS | 回环 HTTP 来源 | MCP 接受的逗号分隔浏览器来源。请在此添加每个公开浏览器来源。 |
容器始终将本地资源包存储在 /models 下。唯一的模型存储设置是挂载到该路径的主机目录。若只运行 CLM,请设置 DECIDEALOT_LAYA_ENABLED=false、DECIDEALOT_VON_ENABLED=false,并配置 DECIDEALOT_CLM_EMBEDDINGS_URL。若只运行 Jev,请禁用 Laya 和 Von,不配置 CLM,并提供 DECIDEALOT_TYPESAFE_API_KEY;无需挂载 /models。CLM 的 embeddings 端点和 TypeSafe 的 Jev API 会接收决策状态和标准,因此仅当允许这些数据离开主机时才使用它们。仅在单主机场景下保留回环绑定。在将 Decidealot 部署到代理、隧道或公共地址之后,请将 DECIDEALOT_API_KEY 设为真实密钥,要求每个调用方提供 Authorization: Bearer <your-key>,并配置上述精确的 MCP 主机和来源允许列表。
CLM 嵌入与缓存
CLM 会先对编码器向量进行归一化,然后再应用其投影头。重复的候选文本会复用有大小上限的进程内缓存;原始决策状态绝不会被缓存。卸载 CLM 时会清除此缓存。usage.input_tokens 仅报告实际发起的嵌入调用所计费的 token 数量。字节数上限不等于 token 数量上限:请将编码器配置为拒绝超出其上下文限制的输入,而不是静默截断。量化后的 Qwen 编码器并不等同于上游的全精度编码器,仅匹配向量宽度并不能证明准确度相当。
CUDA
psyb0t/decidealot:latest-cuda 使用 CUDA 12.6,需要兼容的 NVIDIA 驱动、NVIDIA Container Toolkit 和 --gpus all。CUDA 镜像仅支持 amd64。除非推理速度和模型内存需求足以证明 GPU 配置的必要性,否则默认应使用 CPU 镜像。
model_directory="${model_directory:-$HOME/.local/share/decidealot/models}"
runtime_uid=$(id -u)
runtime_gid=$(id -g)
mkdir --parents "$model_directory"
docker run --detach --name decidealot --init --restart unless-stopped \
--user "$runtime_uid:$runtime_gid" \
--gpus all --read-only --cap-drop ALL --security-opt no-new-privileges:true \
--pids-limit 512 --memory 8g --cpus 4 \
--tmpfs /tmp:rw,noexec,nosuid,size=128m \
--tmpfs /var/run:rw,noexec,nosuid,size=8m \
--tmpfs /var/cache:rw,exec,nosuid,nodev,size=512m,uid=$runtime_uid,gid=$runtime_gid,mode=0755 \
--log-driver json-file --log-opt max-size=10m --log-opt max-file=5 \
--mount type=bind,source="$model_directory",target=/models \
--publish 127.0.0.1:8080:8080 \
psyb0t/decidealot:latest-cuda
CUDA 需要一个可写的可执行缓存目录,因为 Triton 会在其中编译并加载短生命周期的 CUDA 辅助程序。容器的其余部分仍保持只读且 noexec。部署 提供了完整的 CPU、CUDA、身份验证、持久化存储和主机目录配置说明。
模型存储与卸载
将一个范围尽可能小的主机目录挂载到 /models。Decidealot 会在其中创建并管理 /models/laya、/models/von,以及在启用时创建并管理 /models/clm。Docker 命令会以你当前的主机 UID 和 GID 运行,因此你自行创建的目录无需针对镜像执行 chown 即可写入。只有未提供运行时用户时,镜像才会回退到非 root 用户 1000:1000。
使用完毕后,卸载已加载的本地运行时:
curl --fail --request POST http://127.0.0.1:8080/v1/models/unload
该端点会报告每个已配置的本地提供方,并停止所有已加载且处于空闲状态的提供方。若有本地请求正在运行,它会拒绝卸载任何提供方。停止提供方进程会释放其模型权重、Torch 分配、工作线程和 CUDA 上下文。这不会影响 TypeSafe 托管的 Jev。之后有本地请求时,系统会重新启动相应提供方。
Agent 集成
在包含该技能的版本发布后,从 psyb0t marketplace 安装 Decidealot 技能。该技能会指导 Agent 如何部署 Docker 镜像、选择 Laya、Von、CLM 或 Jev、提交带类型的决策、读取概率、使用直接 MCP,以及仅在客户端需要时使用 stdio 桥接。
claude plugin marketplace add psyb0t/agents
claude plugin install decidealot@psyb0t
codex plugin marketplace add psyb0t/agents
codex plugin add decidealot@psyb0t
OpenClaw 可以安装该技能或其 stdio 桥接。该桥接会将 stdio 流量转发到你已运行的 Decidealot 容器。
openclaw skills install @psyb0t/decidealot
openclaw plugins install clawhub:@psyb0t/decidealot
文档
| 文档 | 内容 |
|---|---|
| API | TypeSafe 请求和响应结构、错误、身份验证、别名及提供方生命周期。 |
| 部署 | 加固的 Docker 命令、CUDA、持久化模型目录和暴露规则。 |
| 变更日志 | 按版本列出的用户可见变更。 |
许可证
Decidealot 代码采用 WTFPL 许可证。Laya、Von、CLM、PyTorch、Transformers 以及每个下载的模型均保留各自的上游许可证。将模型用于商业产品前,请先阅读相关许可证。
评论
一个开放协议,规定了 AI 应用如何以统一方式连接外部工具与数据源。客户端负责与模型对话,MCP 服务负责提供工具、资源和提示模板,两者通过标准消息通信,同一个服务可以被不同客户端复用。