Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 31 additions & 1 deletion client/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -166,7 +166,7 @@ export OPENROUTER_API_KEY=sk-or-...

### `llm` 字段说明

- `adapter`:模型适配器,当前支持 `openai`、`openrouter`、`anthropic`。不写时默认是 `openai`。
- `adapter`:模型适配器,当前支持 `openai`、`openrouter`、`anthropic`、`huawei-modelarts`。不写时默认是 `openai`。
- `model`:模型名,例如 `gpt-4o-mini`、`gpt-4.1`、`qwen/qwen3-coder:free`。
- `api_key`:模型服务密钥。也可以通过环境变量提供。
- `endpoint`:自定义 provider base URL。对 `openrouter`/`anthropic` 来说分别映射到各自 SDK 的 `base_url`。
Expand Down Expand Up @@ -283,6 +283,35 @@ export ANTHROPIC_MODEL=claude-sonnet-4-5

- `client/examples/config.anthropic.example.json`

Huawei ModelArts:

```json
{
"llm": {
"adapter": "huawei-modelarts",
"model": "glm-5"
}
}
```

配合环境变量:

```bash
export HUAWEI_MODELARTS_API_KEY=your-key
# 可选,默认就是 https://api.modelarts-maas.com/v2
export HUAWEI_MODELARTS_BASE_URL=https://api.modelarts-maas.com/v2
```

说明:

- 默认 base URL 是 `https://api.modelarts-maas.com/v2`
- runtime 实际调用 OpenAI SDK 风格的 `/chat/completions`
- 也可以通过 `llm.endpoint` 或 `--endpoint` 临时覆盖 base URL

仓库示例文件:

- `client/examples/config.huawei-modelarts.example.json`

OpenAI-compatible / 自建模型网关:

```json
Expand Down Expand Up @@ -414,6 +443,7 @@ python -m client doctor
- `openai` adapter:需要 `langchain-openai`
- `openrouter` adapter:需要 `openai`
- `anthropic` adapter:需要 `anthropic`
- `huawei-modelarts` adapter:需要 `openai`

否则 `doctor` 会提示 adapter probe 或依赖缺失,runtime 也无法正常启动。

Expand Down
7 changes: 6 additions & 1 deletion client/commands/info.py
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,9 @@ def build_doctor_report(
"openrouter": bool(config.llm.api_key or os.getenv("OPENROUTER_API_KEY")),
"openai": bool(config.llm.api_key or os.getenv("OPENAI_API_KEY")),
"anthropic": bool(config.llm.api_key or os.getenv("ANTHROPIC_API_KEY")),
"huawei-modelarts": bool(
config.llm.api_key or os.getenv("HUAWEI_MODELARTS_API_KEY")
),
}
workspace = Path(config.workspace_dir).expanduser().resolve()
user_dir = Path(config.user_dir).expanduser().resolve()
Expand Down Expand Up @@ -97,7 +100,7 @@ def build_doctor_report(
warnings: list[str] = []
if not diagnostics["workspace_exists"]:
warnings.append("workspace_dir does not exist")
if adapter not in {"openai", "openrouter", "anthropic"}:
if adapter not in {"openai", "openrouter", "anthropic", "huawei-modelarts"}:
warnings.append(f"unsupported adapter configured: {adapter}")
if not diagnostics["llm"]["api_key_present"]:
warnings.append(f"missing API key for adapter={adapter}")
Expand All @@ -115,6 +118,8 @@ def build_doctor_report(
warnings.append("langchain-openai is required for openai adapter")
if adapter == "anthropic" and not deps["anthropic_sdk_installed"]:
warnings.append("anthropic SDK is required for anthropic adapter")
if adapter == "huawei-modelarts" and not deps["openai_sdk_installed"]:
warnings.append("openai SDK is required for huawei-modelarts adapter")
diagnostics["warnings"] = warnings
diagnostics["ok"] = len(warnings) == 0
return diagnostics
6 changes: 6 additions & 0 deletions client/examples/config.huawei-modelarts.example.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"llm": {
"adapter": "huawei-modelarts",
"model": "modelarts-pro"
}
}
2 changes: 1 addition & 1 deletion client/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -1538,7 +1538,7 @@ def _build_parser() -> argparse.ArgumentParser:
parser = argparse.ArgumentParser(description="DARE external CLI")
parser.add_argument("--workspace", default=str(Path.cwd()), help="workspace root path")
parser.add_argument("--user-dir", default=str(Path.home()), help="user directory path")
parser.add_argument("--adapter", default=None, help="llm adapter override (openai/openrouter/anthropic)")
parser.add_argument("--adapter", default=None, help="llm adapter override (openai/openrouter/anthropic/huawei-modelarts)")
parser.add_argument("--model", default=None, help="llm model override")
parser.add_argument("--api-key", default=None, help="llm api key override")
parser.add_argument("--endpoint", default=None, help="llm endpoint override")
Expand Down
8 changes: 7 additions & 1 deletion dare_framework/model/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,12 @@
from dare_framework.model.builtin_prompt_loader import BuiltInPromptLoader
from dare_framework.model.filesystem_prompt_loader import FileSystemPromptLoader
from dare_framework.model.layered_prompt_store import LayeredPromptStore
from dare_framework.model.adapters import AnthropicModelAdapter, OpenAIModelAdapter, OpenRouterModelAdapter
from dare_framework.model.adapters import (
AnthropicModelAdapter,
HuaweiModelArtsModelAdapter,
OpenAIModelAdapter,
OpenRouterModelAdapter,
)

__all__ = [
"IModelAdapter",
Expand All @@ -25,6 +30,7 @@
"FileSystemPromptLoader",
"LayeredPromptStore",
"AnthropicModelAdapter",
"HuaweiModelArtsModelAdapter",
"OpenAIModelAdapter",
"OpenRouterModelAdapter",
]
8 changes: 7 additions & 1 deletion dare_framework/model/adapters/__init__.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,13 @@
"""Model adapters."""

from dare_framework.model.adapters.anthropic_adapter import AnthropicModelAdapter
from dare_framework.model.adapters.huawei_modelarts_adapter import HuaweiModelArtsModelAdapter
from dare_framework.model.adapters.openai_adapter import OpenAIModelAdapter
from dare_framework.model.adapters.openrouter_adapter import OpenRouterModelAdapter

__all__ = ["AnthropicModelAdapter", "OpenAIModelAdapter", "OpenRouterModelAdapter"]
__all__ = [
"AnthropicModelAdapter",
"HuaweiModelArtsModelAdapter",
"OpenAIModelAdapter",
"OpenRouterModelAdapter",
]
Loading
Loading