mirror of
https://github.com/agentscope-ai/ReMe.git
synced 2026-10-13 04:01:35 +00:00
Merge e631a7a547 into 084c02e43a
This commit is contained in:
commit
63c4c7213f
7 changed files with 123 additions and 0 deletions
|
|
@ -151,6 +151,11 @@ EOF
|
|||
|
||||
Basic file operations, BM25 search, wikilink traversal, and reading proactive topics can run without LLM credentials.
|
||||
|
||||
`LLM_BACKEND` selects the provider wrapper registered in `reme/components/as_llm` (default `openai`). You can also use
|
||||
[OrcaRouter](https://www.orcarouter.ai), an OpenAI-compatible gateway, with `LLM_BACKEND=orcarouter`,
|
||||
`LLM_MODEL_NAME=orcarouter/auto`, and an `LLM_API_KEY` from OrcaRouter; `LLM_BASE_URL` then defaults to
|
||||
`https://api.orcarouter.ai/v1`.
|
||||
|
||||
> [!NOTE]
|
||||
> To enable embedding-based semantic retrieval, uncomment `components.as_embedding` and
|
||||
> `components.embedding_store` in [`reme/config/default.yaml`](reme/config/default.yaml), then change
|
||||
|
|
|
|||
|
|
@ -142,6 +142,11 @@ EOF
|
|||
|
||||
基础文件读写、BM25 检索、wikilink 遍历和 proactive topics 读取不需要 LLM 凭证,可以跳过此步骤并直接启动服务。
|
||||
|
||||
`LLM_BACKEND` 选择 `reme/components/as_llm` 中注册的 provider wrapper(默认 `openai`)。也可以接入
|
||||
[OrcaRouter](https://www.orcarouter.ai)(兼容 OpenAI 协议的中转网关):设 `LLM_BACKEND=orcarouter`、
|
||||
`LLM_MODEL_NAME=orcarouter/auto`,并用 OrcaRouter 的 `LLM_API_KEY`;`LLM_BASE_URL` 可缺省,
|
||||
默认 `https://api.orcarouter.ai/v1`。
|
||||
|
||||
> [!NOTE]
|
||||
> 如需启用基于 embedding 的语义检索,请取消 [`reme/config/default.yaml`](reme/config/default.yaml) 中
|
||||
> `components.as_embedding` 和 `components.embedding_store` 的注释,并将
|
||||
|
|
|
|||
|
|
@ -47,6 +47,19 @@ EOF
|
|||
|
||||
You can initially omit the LLM configuration if you only need basic file operations and BM25 retrieval.
|
||||
|
||||
`LLM_BACKEND` selects the provider wrapper registered in
|
||||
`reme/components/as_llm`. Besides the built-in providers (`openai`, `anthropic`, `deepseek`,
|
||||
`dashscope`, `gemini`, `moonshot`, `ollama`, `xai`), you can point at
|
||||
[OrcaRouter](https://www.orcarouter.ai), an OpenAI-compatible gateway, by setting:
|
||||
|
||||
```bash
|
||||
LLM_BACKEND=orcarouter
|
||||
LLM_MODEL_NAME=orcarouter/auto
|
||||
LLM_API_KEY=sk-orca-...
|
||||
```
|
||||
|
||||
`LLM_BASE_URL` stays optional — when unset it defaults to `https://api.orcarouter.ai/v1`.
|
||||
|
||||
---
|
||||
|
||||
## Start the Service
|
||||
|
|
|
|||
|
|
@ -46,6 +46,17 @@ EOF
|
|||
|
||||
只跑基础文件读写和 BM25 检索,可以先不配。
|
||||
|
||||
`LLM_BACKEND` 选择 `reme/components/as_llm` 中注册的 provider wrapper。除内置 provider(`openai`、`anthropic`、`deepseek`、`dashscope`、`gemini`、`moonshot`、`ollama`、`xai`)外,也可以接入兼容 OpenAI 协议的中转网关
|
||||
[OrcaRouter](https://www.orcarouter.ai):
|
||||
|
||||
```bash
|
||||
LLM_BACKEND=orcarouter
|
||||
LLM_MODEL_NAME=orcarouter/auto
|
||||
LLM_API_KEY=sk-orca-...
|
||||
```
|
||||
|
||||
`LLM_BASE_URL` 可不填,缺省时默认 `https://api.orcarouter.ai/v1`。
|
||||
|
||||
---
|
||||
|
||||
## 启动
|
||||
|
|
|
|||
|
|
@ -3,6 +3,11 @@ EMBEDDING_BASE_URL=https://dashscope.aliyuncs.com/compatible-mode/v1
|
|||
LLM_API_KEY=sk-xxx
|
||||
LLM_BASE_URL=https://dashscope.aliyuncs.com/compatible-mode/v1
|
||||
|
||||
# OpenAI-compatible gateway: LLM_BACKEND=orcarouter
|
||||
# LLM_API_KEY=sk-orca-...
|
||||
# LLM_MODEL_NAME=orcarouter/auto
|
||||
# LLM_BASE_URL is optional and defaults to https://api.orcarouter.ai/v1
|
||||
|
||||
# Optional data-source mirrors. Unset variables use the official services.
|
||||
# HF_MIRROR_URL=https://hf-mirror.com
|
||||
# ARXIV_MIRROR_URL=https://export.arxiv.org
|
||||
|
|
|
|||
|
|
@ -1,5 +1,7 @@
|
|||
"""LLM model wrappers for AgentScope."""
|
||||
|
||||
from typing import Literal
|
||||
|
||||
from agentscope.credential import (
|
||||
AnthropicCredential,
|
||||
CredentialBase,
|
||||
|
|
@ -12,6 +14,7 @@ from agentscope.credential import (
|
|||
XAICredential,
|
||||
)
|
||||
from agentscope.model import ChatModelBase
|
||||
from pydantic import ConfigDict, Field, field_validator
|
||||
|
||||
from ..base_component import BaseComponent
|
||||
from ..component_registry import R
|
||||
|
|
@ -66,6 +69,46 @@ class OpenAIAsLLM(BaseAsLLM):
|
|||
credential_cls = OpenAICredential
|
||||
|
||||
|
||||
_ORCAROUTER_BASE_URL = "https://api.orcarouter.ai/v1"
|
||||
|
||||
|
||||
class OrcaRouterCredential(OpenAICredential):
|
||||
"""OpenAI-compatible credential for the OrcaRouter gateway.
|
||||
|
||||
OrcaRouter exposes an OpenAI-compatible ``chat/completions`` endpoint at
|
||||
``https://api.orcarouter.ai/v1``. The shared LLM config passes
|
||||
``base_url: ${LLM_BASE_URL:-}``, so an unset ``LLM_BASE_URL`` yields an
|
||||
empty string; this credential falls back to the hosted gateway in that
|
||||
case while still allowing a custom/self-hosted endpoint.
|
||||
"""
|
||||
|
||||
model_config = ConfigDict(
|
||||
title="OrcaRouter API",
|
||||
)
|
||||
|
||||
type: Literal["orcarouter_credential"] = "orcarouter_credential"
|
||||
"""The credential type."""
|
||||
|
||||
base_url: str = Field(
|
||||
default=_ORCAROUTER_BASE_URL,
|
||||
description="The base URL for the OrcaRouter API.",
|
||||
)
|
||||
"""The base URL for the OrcaRouter API."""
|
||||
|
||||
@field_validator("base_url", mode="before")
|
||||
@classmethod
|
||||
def _default_base_url(cls, value: str | None) -> str:
|
||||
"""Fall back to the hosted gateway when the shared config leaves the field empty."""
|
||||
return value or _ORCAROUTER_BASE_URL
|
||||
|
||||
|
||||
@R.register("orcarouter")
|
||||
class OrcaRouterAsLLM(BaseAsLLM):
|
||||
"""OrcaRouter chat model wrapper (OpenAI-compatible gateway)."""
|
||||
|
||||
credential_cls = OrcaRouterCredential
|
||||
|
||||
|
||||
@R.register("anthropic")
|
||||
class AnthropicAsLLM(BaseAsLLM):
|
||||
"""Anthropic chat model wrapper."""
|
||||
|
|
@ -118,6 +161,7 @@ class XAIAsLLM(BaseAsLLM):
|
|||
__all__ = [
|
||||
"BaseAsLLM",
|
||||
"OpenAIAsLLM",
|
||||
"OrcaRouterAsLLM",
|
||||
"AnthropicAsLLM",
|
||||
"DashScopeAsLLM",
|
||||
"DeepSeekAsLLM",
|
||||
|
|
|
|||
40
tests/unit/test_orcarouter_provider.py
Normal file
40
tests/unit/test_orcarouter_provider.py
Normal file
|
|
@ -0,0 +1,40 @@
|
|||
"""Tests for the OrcaRouter LLM provider."""
|
||||
|
||||
# pylint: disable=missing-function-docstring,missing-class-docstring,unused-argument
|
||||
|
||||
from reme.components.as_llm import OrcaRouterAsLLM, OrcaRouterCredential
|
||||
from reme.components.component_registry import R, create_application_registry
|
||||
from reme.enumeration import ComponentEnum
|
||||
|
||||
|
||||
def test_orcarouter_registered_in_builtin_registry():
|
||||
assert R.get(ComponentEnum.AS_LLM, "orcarouter") is OrcaRouterAsLLM
|
||||
|
||||
|
||||
def test_application_registry_includes_orcarouter():
|
||||
reg = create_application_registry()
|
||||
assert reg.get(ComponentEnum.AS_LLM, "orcarouter") is OrcaRouterAsLLM
|
||||
|
||||
|
||||
def test_orcarouter_credential_defaults_to_hosted_gateway():
|
||||
credential = OrcaRouterCredential(api_key="sk-orca-test")
|
||||
assert credential.base_url == "https://api.orcarouter.ai/v1"
|
||||
|
||||
|
||||
def test_orcarouter_credential_empty_base_url_falls_back_to_gateway():
|
||||
# The shared config passes ``base_url: ${LLM_BASE_URL:-}``, which yields an
|
||||
# empty string when LLM_BASE_URL is unset.
|
||||
credential = OrcaRouterCredential(api_key="sk-orca-test", base_url="")
|
||||
assert credential.base_url == "https://api.orcarouter.ai/v1"
|
||||
|
||||
|
||||
def test_orcarouter_credential_custom_base_url_kept():
|
||||
credential = OrcaRouterCredential(
|
||||
api_key="sk-orca-test",
|
||||
base_url="https://selfhosted.example.com/v1",
|
||||
)
|
||||
assert credential.base_url == "https://selfhosted.example.com/v1"
|
||||
|
||||
|
||||
def test_orcarouter_credential_reuses_openai_chat_model():
|
||||
assert OrcaRouterCredential.get_chat_model_class().__name__ == "OpenAIChatModel"
|
||||
Loading…
Add table
Reference in a new issue