为 DiscourseAI 自托管开源 LLM

Discourse AI 插件具有许多需要启用大语言模型(LLM)的功能,包括摘要生成、AI Helper、语义搜索、AI Bot 及其代理。你可以使用第三方 API,例如 配置 OpenAI API 密钥 或 配置 Anthropic API 密钥,但 Discourse AI 从第一天起就设计为不依赖于这些服务。

本指南将介绍如何自行运行开源权重模型并将其连接到 Discourse。

此处使用的模型: Qwen/Qwen3.8-27B —— 一款于 2026 年 8 月发布的 27B 稠密模型,具有原生 256K 上下文窗口、图像/视频理解、工具调用功能,并默认启用思维模式。它目前是自建托管的最佳选择:功能足够强大,可用于真实的摘要/代理工作,规模又足够小,可以在单块 GPU 上运行。你可以替换为任何其他喜欢的模型;下文将指出需要更改的参数。

Discourse 对你的推理服务器有什么要求

  • 一个 兼容 OpenAI 的 POST /v1/chat/completions 端点(支持流式传输)。
  • 如果你想让 AI Bot、代理或结构化输出良好运行,需要原生的工具/函数调用功能。如果没有此功能,Discourse 会回退到基于 XML 的工具调用,较弱模型对此处理不佳。
  • 真正的上下文窗口 —— 目标至少 16K tokens,建议 32K+。Discourse 用于摘要和 RAG 的提示大小增长很快。
  • 可选:图像输入,如果你希望模型读取帖子中附带的图像。

只要满足前三项要求的任何方案均可行,因此以下选择主要取决于你的硬件。

设置 适用场景
vLLM 专用 GPU 服务器,显存 ≥24GB(量化)/ 80GB(全精度),持续流量,多用户环境
llama.cpp 消费级 GPU,Apple Silicon,纯 CPU 机器,小型个人论坛
托管 / 云服务 你希望模型不运行在你的笔记本电脑上,也不运行在你的硬件上:任何兼容 OpenAI 的端点

使用 vLLM 运行

vLLM 是 GPU 服务器的推荐引擎:采用 Apache 许可证,开箱即用的兼容 OpenAI 服务器,并对 Qwen 系列提供一流支持。

mkdir -p /opt/vllm-cache
export VLLM_API_KEY="$(openssl rand -hex 24)"

docker run -d --name vllm \
  --runtime nvidia --gpus all \
  -v /opt/vllm-cache:/root/.cache/huggingface \
  -e HF_HOME=/root/.cache/huggingface \
  -e "HF_TOKEN=${HF_TOKEN}" \
  -p 8080:8000 \
  --ipc=host \
  vllm/vllm-openai:latest \
  Qwen/Qwen3.8-27B \
  --host 0.0.0.0 \
  --port 8000 \
  --max-model-len 32768 \
  --reasoning-parser qwen3 \
  --enable-auto-tool-choice \
  --tool-call-parser qwen3_xml \
  --api-key "$VLLM_API_KEY"

关于这些参数的说明:

  • --max-model-len 限制提示+输出的上下文长度,从而影响 KV 缓存。该模型原生支持 256K;32K 对于论坛任务已经绰绰有余,并且能保持显存使用可预测。如果你有足够内存,可以提高该值(或使用 auto)。
  • --reasoning-parser qwen3 将模型的思维过程拆分到一个单独的 reasoning 字段中,而不是直接混入答案。你必须在此后的 Discourse LLM 设置中反映这一选择(见下文)。
  • --enable-auto-tool-choice --tool-call-parser ... 开启原生函数调用。解析器名称在不同 vLLM 版本间可能会变动 —— 如果工具调用返回的是纯文本,请在你的镜像内检查 python3 -m vllm.entrypoints.openai.api_server --help。
  • HF_TOKEN 仅在使用受限模型时需要;--api-key 用于保护你自己的端点。vLLM 文档中的警告:--api-key 仅保护 /v1 路由,因此仍应将服务器置于公网之外。
  • 显存紧张?在缩减上下文之前,先尝试 --quantization fp8(或使用预量化 AWQ 检查点)。多 GPU:添加 --tensor-parallel-size N。

测试它:

curl http://localhost:8080/v1/chat/completions \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer $VLLM_API_KEY" \
  -d '{
    "model": "Qwen/Qwen3.8-27B",
    "messages": [{"role": "user", "content": "What is Discourse?"}],
    "max_tokens": 200
  }'

你应该会收到一个正常的 chat-completion JSON 响应体,其中 message.content 旁边会有 message.reasoning。

使用 llama.cpp 运行

当模型需要适应比 vLLM 要求更少的显存,或者你使用 Apple Silicon、AMD、Vulkan 或 CPU 时,llama.cpp 是合适的工具。其 llama-server 也提供了兼容 OpenAI 的 API。

使用对应后端的容器镜像拉取并运行官方 GGUF 构建版本(这里使用 server-cuda;也存在 server、server-rocm、server-vulkan 等):

export LLAMA_API_KEY="$(openssl rand -hex 24)"

docker run -d --name llama-server \
  --gpus all \
  -p 8080:8080 \
  -v /opt/llama-models:/models \
  ghcr.io/ggml-org/llama.cpp:server-cuda \
  -hf ggml-org/Qwen3.8-27B-GGUF:Q4_K_M \
  --host 0.0.0.0 \
  --port 8080 \
  --alias qwen3.8-27b \
  --api-key "$LLAMA_API_KEY" \
  --ctx-size 16384 \
  --n-gpu-layers auto \
  --flash-attn auto \
  --jinja \
  --reasoning auto
  • Q4_K_M 权重约占 16GB;在 8K 上下文下测得约 18.4 GiB 显存,32K 时约 20 GiB,因此 24GB 显卡配合适中的 --ctx-size 是可以运行的。Unsloth 的 unsloth/Qwen3.8-27B-GGUF:UD-Q4_K_M 是一个流行的替代方案。
  • --jinja 使用模型自带的聊天模板 —— 这是实现原生工具调用工作的关键。
  • --alias 设置 API 报告的名称,以便你在 Discourse 中输入的模型名称与之匹配。
  • --reasoning auto 单独报告思维过程,匹配 vLLM 的 --reasoning-parser 行为。
  • 图像输入需要多模态投影器;使用 -hf 时通常会自动获取,否则请传递 --mmproj /models/mmproj-...gguf(或使用 --no-mmproj 以节省纯文本服务时的显存)。

测试它:

curl http://localhost:8080/v1/chat/completions \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer $LLAMA_API_KEY" \
  -d '{
    "model": "qwen3.8-27b",
    "messages": [{"role": "user", "content": "What is Discourse?"}],
    "max_tokens": 200
  }'

运行其他服务

任何支持 OpenAI chat completions 的服务器 —— 如 SGLang、TensorRT-LLM、LM Studio、企业网关、专用云部署 —— 均可直接使用:在 Discourse 中使用 vLLM 提供程序进行配置,这是一个支持原生工具调用的通用 OpenAI 兼容客户端。

如果你不想自己运行推理,但仍希望避免被大型 API 锁定,Hugging Face Inference Endpoints(现在默认使用 vLLM 作为引擎)可以与 Hugging Face 提供程序配合使用 —— 将其指向端点的 /v1/chat/completions URL。

让你的 Discourse 实例能够访问它

由于 GPU 需求,你通常会在专用机器上运行它。这样做时:

  1. 在服务器前设置一个反向代理并在其上终止 TLS —— Discourse 可以安全地通过 HTTPS 与其通信。
  2. 通过防火墙或客户端证书限制端点,以便只有你的 Discourse 主机可以连接。API 密钥用于身份验证,而不是网络边界。
  3. 将模型缓存保存在持久卷上,以便重启时不会重新下载数十 GB 的数据。

配置 Discourse AI

LLM 连接是通过管理界面而非站点设置进行配置的。前往 /admin/plugins/discourse-ai/ai-llms 并添加一个新的 LLM:

  1. 显示名称 —— 管理员和用户看到的名称。
  2. 名称 —— 在 API 请求中发送;它必须与服务器预期的名称匹配(vLLM 为 Qwen/Qwen3.8-27B,llama.cpp 为你的 --alias)。
  3. 提供程序 —— 对于 vLLM、llama.cpp 和任何其他 OpenAI 兼容服务器选择 vLLM;对于托管在 HF 上的端点选择 Hugging Face。
  4. URL —— 包含路径的完整端点 URL,例如 https://llm.example.com/v1/chat/completions。
  5. API 密钥 —— 手动输入,或引用 AI Secrets 页面中存储的密钥。
  6. Tokenizer —— 对于 Qwen3.8 选择 Qwen(选择匹配你模型家族的分词器)。
  7. 最大提示 tokens / 最大输出 tokens —— 保持总和小于或等于你服务器的 --max-model-len / --ctx-size。例如,对于 32768 token 的服务器:28000 提示和 4096 输出。推理模型会将部分输出预算用于思考,因此不要挤压得太紧。
  8. Vision —— 如果你在提供服务时支持图像并希望模型读取图像,请启用原生视觉功能。
  9. 提供程序选项(vLLM):将 vLLM reasoning parser 设置为 qwen3 以匹配服务器参数,如果你希望 Discourse 按请求控制思维过程,请使用思维覆盖/推理力度/思维 token 预算字段。除非模型的功能调用出错,否则请保留“禁用原生工具”未选中状态。

点击运行测试后再保存:它会发出流式和非流式请求,并告诉你哪个失败了。

保存后,通过 ai_default_llm_model 站点设置将其设为站点默认值,或在 /admin/plugins/discourse-ai/ai-features 中按功能分配。单独的代理在 Agents 页面配置。

一个注意事项:语义搜索嵌入并非来自此模型。 嵌入使用其自己的嵌入模型,单独配置(API 嵌入模型,或通过 ai_hugging_face_tei_endpoint 设置配置的自托管 Text Embeddings Inference 服务器)。如果你希望完全自建托管 AI 搜索,请在你的 LLM 旁边运行一个小的嵌入模型,如 bge-m3。

故障排除

症状 可能原因
端点返回 404 URL 缺少 /v1/chat/completions
model not found 名称 与提供的模型 ID / --alias 不匹配
401 / 403 --api-key 和 LLM 记录之间的 API 密钥不匹配
帖子中出现 JSON 文本形式的工具调用 服务器启动时未进行工具调用解析;Discourse 回退到了 XML 工具
思维文本泄漏到答案中 服务器缺少 --reasoning-parser,或者 Discourse reasoning parser 设置与其不匹配
CUDA 内存不足 降低 --max-model-len,添加 --quantization fp8,或降低 --gpu-memory-utilization
长摘要请求超时 推理模型速度慢;我们的 HTTP 超时时间为 6 分钟 —— 减少上下文,降低思维力度,或禁用思维
答案被截断 一旦计入思维 tokens,Discourse 中的 max output tokens 太小
17 个赞

对于搜索此主题的任何人,包括/用于:
#Llava-Api-keys

我也在使用 vLLM。我还会推荐 openchat v3.5 0106 模型,这是一个 7B 参数模型,性能非常好。

我实际上是以 4 位量化方式运行它的,这样可以运行得更快。

我将此任务分配给一名实习生。有人推荐注册什么特定服务吗?这是为了测试。实习生目前已配置好 OpenAI 测试。运行正常。他们有兴趣尝试 HuggingFace TGI,但似乎我需要为他们提供专用的 GPU 服务器?测试的最低配置是什么?

我可以提供给实习生一些链接吗?

我还没有深入研究这个项目。我只是预计实习生将需要一些资源,并且我正在尝试为实习生的研究提供一些合理的建议。

您好,在使用本地 GPU 服务器上的自签名证书公开 vllm 容器时,我没有找到一种好方法将根 CA 添加到 discourse 容器中,以便它可以安全地通过 HTTPS 访问此本地服务。

例如:

./launcher enter app
curl -L https://vllm.infra.example.com/v1/models
curl: (60) SSL certificate problem: unable to get local issuer certificate
更多详情请参见:https://curl.se/docs/sslcerts.html

curl 无法验证服务器的合法性,因此无法建立安全连接。要了解有关此情况的更多信息以及如何解决,请访问上面提到的网页。

有没有一种好方法可以在 discourse 容器中添加自签名根 CA 证书,并且该证书能在容器镜像更新后继续存在?

据我所知,在 app.yml 中添加它

run:
  - exec: wget ... && update-ca-certificates

只在构建/重建应用程序时效果最好。

欢迎任何提示。

14 篇帖子已拆分为新主题:Getting discourse ai to work with ollama locally

是否可以在 Discourse AI 请求中添加自定义 HTTP 标头?我们有一个配备 GPU 的服务器,可用于各种目的,它具有与 OpenAI 兼容的 API,但出于安全考虑,我们将其置于 API 管理网关之后,这需要一个自定义 HTTP 标头(类似于 SubscriptionKey),我们在此处提供我们的授权密钥。

请注意,此授权密钥用于通过 APIM,它不同于您为 OpenAI API 等服务提供的 API 密钥。

如果可以在 admin/plugins/discourse-ai/ai-llms 设置页面中为每个 LLM 的设置添加自定义标头,那就太好了。也许在“提供商”下拉菜单中有一个“自定义选项”,并提供用于此类用例的附加选项?

1 个赞

快速的答案是添加该标头的插件。一种变通方法可能是使用一个本地代理服务器,您可以通过 Discourse 访问它,它会添加标头并将数据传回 Discourse。一个不可靠的消息来源表明,您可能可以通过 NGINX 来实现这一点,使用类似以下内容:

server {
    listen 80;
    
    location / {
        proxy_pass https://api.example.com;
        proxy_set_header SubscriptionKey xyz;
        proxy_set_header Host $host;
    }
}

可能有一种巧妙的方法可以将该配置添加到 Discourse 的 nginx 配置中的某个秘密路径(该路径也只监听您的服务器)。

1 个赞

你好,

我找不到这些设置:

关于如何使用 Ollama 后端尝试 AI 翻译功能,有什么建议吗?

在 /admin/plugins/discourse-ai/ai-llms/new?llmTemplate=none 创建一个新的 LLM,选择 OpenAI 作为提供商,因为 Ollama 支持 OpenAI compatibility - Ollama 的 OpenAI 兼容接口。

1 个赞

谢谢!我也注意到,只有启用 AI 插件时该 URL 才能正常工作:person_facepalming:

对于新添加的提供商,对于以下必需设置,有什么建议吗?

  1. 分词器
  2. 上下文窗口

对于模型,我在考虑是否使用 stablelm2:1.6b 或 https://ollama.com/library/translategemma:4b,但还不确定。
后者的 README 中有一些关于输入提示的描述。我想知道翻译 AI 功能向 Ollama 发送的查询是什么。 参见 /admin/plugins/discourse-ai/ai-agents/-28/edit

:sweat_smile:

选择与你所选模型最接近的 Tokenizer。对于 Gemma,你可以选择 Gemini 的 Tokenizer。

在此处设置你部署的最大上下文窗口。

请不要这样做。该模型非常非常非常非常非常老旧。这是你能做出的最糟糕的选择。

该模型落后一代,并且有着非常严格的提示词要求,与 Discourse 不兼容。我们期望使用更标准的通用型 LLM。

在该尺寸范围内,我推荐 Qwen 3.5 或 Gemma 4。

3 个赞

再次感谢。我已经设置了相关参数,下载了模型,调整了 Agent,并启用了 AI 翻译功能。让我们看看效果如何。

还有一个问题。我们之前使用的是翻译插件,配合一个慷慨提供的 LibreTranslate 实例。是否无法将 Discourse 的 AI 翻译功能接入该 LibreTranslate 端点?毕竟,这比在没有真正 LLM 能力的服务器上托管 Ollama 实例要容易得多。

那为什么不再继续使用它呢?我们不再更新它,但它仍会按原样继续工作。

Discourse AI 的翻译功能遵循与原始翻译插件完全不同的约束条件,因此我们从头开始构建了它,以应对这个新世界,其中基于 LLM 的翻译比之前通过 ML 翻译 API 所能实现的更好且更便宜。

1 个赞