Chuyển tới nội dung chính

Xây dựng Plugin nhà cung cấp mô hình

Các plugin của nhà cung cấp mô hình khai báo một chương trình phụ trợ suy luận — điểm cuối tương thích với OpenAI, máy chủ Anthropic Messages, API Phản hồi kiểu Codex hoặc bề mặt gốc Bedrock — mà Hermes có thể định tuyến các cuộc gọi `AIAgent

. Mọi nhà cung cấp tích hợp sẵn (OpenRouter, Anthropic, GMI, DeepSeek, Nvidia, ...) đều cung cấp dưới dạng một trong những plugin này. Các bên thứ ba có thể thêm thư mục của riêng họ bằng cách thả một thư mục trong

$Hermes_HOME/plugins/model-providers/ ` mà không có thay đổi nào đối với kho lưu trữ.

mẹo

Plugin nhà cung cấp mô hình là loại plugin nhà cung cấp thứ ba. Những cái khác là Memory Provider Plugins (kiến thức phiên chéo) và Context Engine Plugins (chiến lược nén ngữ cảnh). Cả ba đều tuân theo cùng một mẫu "thả thư mục, khai báo hồ sơ, không chỉnh sửa repo".

Cách hoạt động của tính năng khám phá``providers/init.py._discover_providers()

chạy chậm trong lần đầu tiên bất kỳ mã nào gọi get_provider_profile() hoặc list_providers()

. Thứ tự khám phá:

  1. Các plugin đi kèm

<repo/plugins/model-providers/<name/ ` — giao hàng cùng Hermes 2. Plugin người dùng

$Hermes_HOME/plugins/model-providers/<name/ ` — thả vào bất kỳ thư mục nào; không cần khởi động lại cho các phiên tiếp theo 3. Tệp đơn kế thừa

<repo/providers/<name.py — tương thích ngược cho các bản cài đặt có thể chỉnh sửa ngoài câyCác plugin của người dùng ghi đè các plugin đi kèm cùng tênregister_provider() là người viết cuối cùng giành chiến thắng. Thả thư mục

$Hermes_HOME/plugins/model-providers/gmi/ ` để thay thế cấu hình GMI tích hợp mà không cần chạm vào repo.

Cấu trúc thư mục

` plugins/model-providers/my-provider/ ├── init.py # Calls register_provider(profile) at module-level ├── plugin.YAML # kind: model-provider + metadata (optional but recommended) └── README.md # Setup instructions (optional)

``Tệp được yêu cầu duy nhất là init.py

. plugin.YAML được Hermes plugins sử dụng để xem xét nội tâm và bởi Trình quản lý plugin chung để định tuyến plugin đến trình tải phù hợp; không có nó, trình tải chung sẽ quay trở lại phương pháp phỏng đoán văn bản nguồn.

Ví dụ tối thiểu — một nhà cung cấp khóa API đơn giản


# plugins/model-providers/acme-inference/__init__.py
from providers import register_provider
from providers.base import ProviderProfile`acme = ProviderProfile(
name="acme-inference",
aliases=("acme",),
display_name="Acme Inference",
description="Acme — OpenAI-compatible direct API",
signup_url="https://acme.example.com/keys",
env_vars=("ACME_API_KEY", "ACME_BASE_URL"),
base_url="https://API.acme.example.com/v1",
auth_type="API_key",
default_aux_model="acme-small-fast",
fallback_models=(
"acme-large-v3",
"acme-medium-v3",
"acme-small-fast",
),
)

register_provider(acme)

`

`
``` yaml

# plugins/model-providers/acme-inference/plugin.YAML
name: acme-inference
kind: model-provider
version: 1.0.0
description: Acme Inference — OpenAI-compatible direct API
author: Your Name

`
``Thế thôi. Sau khi bỏ hai tệp này, **tự động nối dây** sau đây không có chỉnh sửa nào khác:

| Tích hợp | Ở đâu | Nó nhận được gì |
|---|---|---|
| Độ phân giải thông tin xác thực |

Hermes_CLI/auth.py
` |
`PROVIDER_REGISTRY["acme-inference"]
` được điền từ hồ sơ |
| Cờ

--provider
` CLI |
`Hermes_CLI/main.py
` | Chấp nhận
`acme-inference
` |
| Xe nhặt
`Hermes model
` |
`Hermes_CLI/models.py
` | Xuất hiện trong
`CANONICAL_PROVIDERS

, danh sách mẫu được lấy từ

\&#123;base_url&#125;/models
` |
|
`Hermes doctor
` |
`Hermes_CLI/doctor.py
` | Kiểm tra sức khỏe đầu dò
`ACME_API_KEY

+

\&#123;base_url&#125;/models
` |
|
`Hermes setup
` |
`Hermes_CLI/config.py
` |
`ACME_API_KEY
` xuất hiện trong
`OPTIONAL_ENV_VARS
` và trình hướng dẫn thiết lập |
| Ánh xạ ngược URL |

agent/model_metadata.py
` | Tên máy chủ → tên nhà cung cấp để tự động phát hiện |
| Mô hình phụ trợ |

agent/auxiliary_CLIent.py
` | Sử dụng
`default_aux_model
` để nén/tóm tắt |
| Độ phân giải thời gian chạy |

Hermes_CLI/runtime_provider.py
` | Trả về đúng
`base_url

,
`API_key

,
`API_mode
` |
| Vận tải |

agent/transports/chat_completions.py
` | Đường dẫn hồ sơ tạo kwargs thông qua
`prepare_messages
` /
`build_extra_body
` /
`build_API_kwargs_extras
` |

## trường Hồ sơ nhà cung cấp

Định nghĩa đầy đủ trong
`providers/base.py

. Những cái hữu ích nhất:| Lĩnh vực | Loại | Mục đích |
|---|---|---|
|
`name
` | str | Id Canonical - khớp với
`model.provider
` trong
`config.yaml
` và cờ

--provider
` |
|
`aliases
` |
`tuple[str, ...]
` | Các tên thay thế được giải quyết bởi
`get_provider_profile()
` (ví dụ:
`grok
` →
`xai

) |
|
`API_mode
` | str |

chat_completions
` \|
`Codex_responses
` \|
`Anthropic_messages
` \|
`bedrock_converse
` |
|
`display_name
` | str | Nhãn con người hiển thị trong bộ chọn
`Hermes model
` |
|
`description
` | str | Phụ đề bộ chọn |
|
`signup_url
` | str | Hiển thị trong quá trình thiết lập lần chạy đầu tiên ("lấy khóa API tại đây") |
|
`env_vars
` |
`tuple[str, ...]
` | Các loại env khóa API theo thứ tự ưu tiên; mục nhập

*_BASE_URL
` cuối cùng được sử dụng làm ghi đè URL cơ sở của người dùng |
|
`base_url
` | str | Điểm cuối suy luận mặc định |
|
`models_url
` | str | URL danh mục rõ ràng (quay lại

\&#123;base_url&#125;/models

) |
|
`auth_type
` | str |

API_key
` \|
`OAuth_device_code
` \|
`OAuth_external
` \|
`copilot
` \|
`aws_SDK
` \|
`external_process
` |
|
`fallback_models
` |
`tuple[str, ...]
` | Danh sách tuyển chọn hiển thị khi tìm nạp danh mục trực tiếp không thành công |
|
`default_headers
` |
`dict[str, str]
` | Được gửi theo mọi yêu cầu (ví dụ:
`Editor-Version
` của Copilot) |
|
`fixed_temperature
` | Bất kỳ |

None
` = sử dụng giá trị của người gọi;
`OMIT_TEMPERATURE
` canh gác = hoàn toàn không gửi nhiệt độ (Kimi) |
|
`default_max_tokens
` |
`int \| None
` | Giới hạn max_tokens cấp nhà cung cấp (Nvidia: 16384) |
|
`default_aux_model
` | str | Mô hình giá rẻ cho các nhiệm vụ phụ trợ (nén, hiển thị, tóm tắt) |

## Móc có thể ghi đè

Phân lớp
`ProviderProfile
` dành cho những điều kỳ quặc không tầm thường:

``` python
from typing import Any
from providers.base import ProviderProfile`class AcmeProfile(ProviderProfile):
def prepare_messages(self, messages: list[dict[str, Any]]) -> list[dict[str, Any]]:
"""Provider-specific message preprocessing. Runs after Codex
sanitization, before developer-role swap. Default: pass-through."""

# Example: Qwen normalizes plain-text content to a list-of-parts
# array and injects cache_control; Kimi rewrites tool-call JSON
return messages`def build_extra_body(self, *, session_id=None, **context) -> dict:
"""Provider-specific extra_body fields merged into the API call.
Context includes: session_id, provider_preferences, model, base_url,
reasoning_config. Default: empty dict."""
# Example: OpenRouter's provider-preferences block,
# Gemini's thinking_config translation.
return \&#123;&#125;`def build_API_kwargs_extras(self, *, reasoning_config=None, **context):
"""Returns (extra_body_additions, top_level_kwargs). Needed when some
fields go top-level (Kimi's reasoning_effort) and some go in extra_body
(OpenRouter's reasoning dict). Default: (\&#123;&#125;, \&#123;&#125;)."""
return \&#123;&#125;, \&#123;&#125;`def fetch_models(self, *, API_key=None, timeout=8.0) -> list[str] | None:
"""Live catalog fetch. Default hits \&#123;models_url or base_url&#125;/models with
Bearer auth. Override for: custom auth (Anthropic), no REST endpoint
(Bedrock → None), or public/unauthenticated catalogs (OpenRouter)."""
return super().fetch_models(API_key=API_key, timeout=timeout)

`

## Ví dụ tham khảo hook

Hãy xem các plugin đi kèm này để biết thành ngữ:

| Plugin | Tại sao nhìn |
|---|---|
|
`plugins/model-providers/OpenRouter/
` | Trình tổng hợp với các tùy chọn của nhà cung cấp, danh mục mô hình công khai |
|
`plugins/model-providers/Gemini/
` | Bản dịch
`thinking_config
` (dạng gốc + biểu mẫu lồng nhau tương thích với OpenAI) |
|
`plugins/model-providers/Kimi-coding/
` |
`OMIT_TEMPERATURE

,
`extra_body.thinking

,
`reasoning_effort
` cấp cao nhất |
|
`plugins/model-providers/qwen-OAuth/
` | Chuẩn hóa tin nhắn, chèn
`cache_control

, độ phân giải cao VL |
|
`plugins/model-providers/nous/
` | Thẻ ghi công, "bỏ qua lý do khi bị vô hiệu hóa" |
|
`plugins/model-providers/custom/
` | OLlama
`num_ctx

+
`think: false
` kỳ quặc |
|
`plugins/model-providers/bedrock/
` |
`API_mode="bedrock_converse"

,
`fetch_models
` trả về Không có (không có điểm cuối REST) ​​|

## Ghi đè người dùng - thay thế phần tích hợp sẵn mà không cần chỉnh sửa repo

Giả sử bạn muốn trỏ
`gmi
` vào điểm cuối dàn dựng riêng tư của mình để thử nghiệm. Tạo

~/.Hermes/plugins/model-providers/gmi/__init__.py

:

``` python
from providers import register_provider
from providers.base import ProviderProfile`register_provider(ProviderProfile(
name="gmi",
aliases=("gmi-cloud", "gmicloud"),
env_vars=("GMI_API_KEY",),
base_url="https://gmi-staging.internal.example.com/v1",
auth_type="API_key",
default_aux_model="Google/Gemini-3.1-flash-lite-preview",
))

`
``Phiên tiếp theo,
`get_provider_profile("gmi").base_url
` trả về URL dàn dựng. Không có bản vá repo, không xây dựng lại. Vì các plugin của người dùng được phát hiện sau các plugin được đóng gói nên lệnh gọi
`register_provider()
` của người dùng sẽ thắng.

## lựa chọn API_mode

Bốn giá trị được công nhận. Hermes chọn một chiếc dựa trên:
1. Ghi đè rõ ràng của người dùng (
`config.yaml
`
`model.API_mode
` khi được đặt)

2. Công văn theo từng mô hình của OpenCode (
`opencode_model_API_mode
` dành cho Zen và Go)
3. Tự động phát hiện URL — hậu tố

/Anthropic
` →
`Anthropic_messages

,
`API.OpenAI.com
` →
`Codex_responses

,
`API.x.ai
` →
`Codex_responses

,

/coding
` trên miền Kimi →
`chat_completions

4. **Hồ sơ
`API_mode

** làm dự phòng khi phát hiện URL không tìm thấy gì
5.
`chat_completions
` mặc định

Đặt
`profile.API_mode
` để khớp với mặc định mà nhà cung cấp của bạn cung cấp — nó hoạt động như một gợi ý. Ghi đè URL người dùng vẫn thắng.

## Các loại xác thực`|
`auth_type
` | Ý nghĩa | Ai sử dụng nó |
|---|---|---|
|
`API_key
` | Biến env đơn mang khóa API tĩnh | Hầu hết các nhà cung cấp |
|
`OAuth_device_code
` | Luồng OAuth mã thiết bị ||
|
`OAuth_external
` | Người dùng đăng nhập ở nơi khác, mã thông báo sẽ rơi vào
`auth.JSON
` | OAuth nhân loại, MiniMax OAuth, Mã đám mây Gemini, Cổng thông tin Qwen, Nous Portal |
|
`copilot
` | Chu kỳ làm mới mã thông báo GitHub Copilot | Chỉ plugin
`copilot
` |
|
`aws_SDK
` | Chuỗi thông tin xác thực AWS SDK (vai trò IAM, hồ sơ, env) | Chỉ plugin
`bedrock
` |
|
`external_process
` | Xác thực được xử lý bởi một quy trình con mà tác nhân sinh ra | Chỉ plugin
`copilot-ACP
` |Cổng
`auth_type
` mà đường dẫn mã coi nhà cung cấp của bạn là "nhà cung cấp khóa API đơn giản" — nếu không phải là
`API_key
` thì Trình quản lý plugin vẫn ghi lại tệp kê khai nhưng tính năng tự động hóa cấp CLI của Hermes (kiểm tra của bác sĩ, cờ

--provider

, ủy quyền của trình hướng dẫn thiết lập) có thể bỏ qua nó.

## Thời điểm khám phá

Việc khám phá nhà cung cấp **lười biếng** — được kích hoạt bởi lệnh gọi
`get_provider_profile()
` hoặc
`list_providers()
` đầu tiên trong quy trình. Trong thực tế, điều này xảy ra sớm khi khởi động (tải mô-đun
`auth.py
` mở rộng
`PROVIDER_REGISTRY
` một cách háo hức). Nếu bạn cần xác minh plugin của mình đã được tải, hãy chạy:

``` bash
Hermes doctor

`
``— hồ sơ
`auth_type="API_key"
` thành công xuất hiện trong phần Kết nối nhà cung cấp với đầu dò

/models

.

Đối với kiểm tra theo chương trình:

`Python
from providers import list_providers
for p in list_providers():
print(p.name, p.base_url, p.API_mode)

`

## Kiểm tra plugin của bạn

Trỏ
`Hermes_HOME
` vào thư mục tạm thời để bạn không làm ô nhiễm cấu hình thực của mình:

`bash
export Hermes_HOME=/tmp/Hermes-plugin-test
mkdir -p $Hermes_HOME/plugins/model-providers/my-provider
cat > $Hermes_HOME/plugins/model-providers/my-provider/__init__.py `&lt;&lt;\'EOF\'
from providers import register_provider
from providers.base import ProviderProfile
register_provider(ProviderProfile(
name="my-provider",
env_vars=("MY_API_KEY",),
base_url="https://API.my-provider.example.com/v1",
auth_type="API_key",
))
EOF`export MY_API_KEY=your-test-key
Hermes -z "hello" --provider my-provider -m some-model

`

## Tích hợp Trình quản lý plugin chung``PluginManager
` chung (thứ mà
`Hermes plugins
` hoạt động) **thấy** các plugin của nhà cung cấp mô hình nhưng không nhập chúng -
`providers/__init__.py
` sở hữu vòng đời của chúng. Người quản lý ghi lại bảng kê khai để xem xét nội tâm và phân loại theo
`kind: model-provider

. Khi bạn thả một plugin người dùng không được gắn nhãn vào

$Hermes_HOME/plugins/
` và ngẫu nhiên gọi
`register_provider
` bằng
`ProviderProfile

, trình quản lý sẽ tự động ép buộc plugin đó thành
`kind: model-provider
` thông qua phương pháp phỏng đoán văn bản nguồn — vì vậy, plugin vẫn định tuyến chính xác ngay cả khi không có
`plugin.YAML

.

## Phân phối qua pip

Giống như bất kỳ plugin Hermes nào, nhà cung cấp mô hình có thể gửi dưới dạng gói pip. Thêm điểm vào
`pyproject.TOML
` của bạn:

`TOML
[project.entry-points."Hermes.plugins"]
acme-inference = "acme_Hermes_plugin:register"

`
``…trong đó
`acme_Hermes_plugin:register
` là hàm gọi
`register_provider(profile)

. Trình quản lý plugin chung chọn các plugin điểm đầu vào trong
`discover_and_load()

. Đối với plugin pip
`kind: model-provider

, bạn vẫn cần khai báo loại trong bảng kê khai của mình (hoặc dựa vào phương pháp phỏng đoán văn bản nguồn).

Xem [Building a Hermes Plugin](/docs/guides/build-a-Hermes-plugin#distribute-via-pip) để biết thông tin thiết lập điểm vào đầy đủ.

## Các trang liên quan
- [Provider Runtime](/docs/developer-guide/provider-runtime) — ưu tiên độ phân giải + nơi mỗi lớp đọc hồ sơ

- [Adding Providers](/docs/developer-guide/adding-providers) — danh sách kiểm tra toàn diện dành cho phần phụ trợ suy luận mới (bao gồm cả đường dẫn plugin nhanh và tích hợp CLI/auth đầy đủ)
- [Memory Provider Plugins](/docs/developer-guide/memory-provider-plugin)
- [Context Engine Plugins](/docs/developer-guide/context-engine-plugin)
- [Building a Hermes Plugin](/docs/guides/build-a-Hermes-plugin) — soạn thảo plugin chung