Skip to content

Commit e272400

Browse files
committed
feat: 新增对使用oneapi接口的claude适配
1 parent 97be8ef commit e272400

4 files changed

Lines changed: 35 additions & 15 deletions

File tree

.env.example

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,14 +12,16 @@ DEEPSEEK_MODEL=deepseek-reasoner #如果是siliconflow,则使用 deepseek-ai/D
1212

1313

1414
# Claude API KEY,默认为 Claude 官方 API,只推荐 Claude 3.5 Sonnet 模型,不推荐其他模型
15-
CLAUDE_API_KEY=your_claude_api_key #or your_openrouter_api_key
15+
CLAUDE_API_KEY=your_claude_api_key
1616
CLAUDE_MODEL=claude-3-5-sonnet-20241022
1717

18-
# 是否使用 OpenRouter 的 Claude 服务
19-
#如果使用 OpenRouter,则设置为 true,否则设置为 false
20-
USE_OPENROUTER=false
18+
# Claude Provider
19+
# 若使用官方则填anthropic, 使用OpenRouter则填openrouter
20+
# 若使用中转平台(国内大多数中转服务均为OneApi/基于前者的NewApi)则填oneapi
21+
CLAUDE_PROVIDER=anthropic
2122

2223
# 如果使用 OpenRouter,这里填写 OpenRouter 的 API URL https://openrouter.ai/api/v1/chat/completions,
24+
# 如果使用中转平台则填写相应的 API URL: 例如 https://api.oneapi.com/v1/chat/completions
2325
# 默认为 Anthropic 的 API URL https://api.anthropic.com/v1/messages
2426
CLAUDE_API_URL=https://api.anthropic.com/v1/messages
2527

app/clients/claude_client.py

Lines changed: 24 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66

77

88
class ClaudeClient(BaseClient):
9-
def __init__(self, api_key: str, api_url: str = "https://api.anthropic.com/v1/messages", is_openrouter: bool = False):
9+
def __init__(self, api_key: str, api_url: str = "https://api.anthropic.com/v1/messages", provider: str = "anthropic"):
1010
"""初始化 Claude 客户端
1111
1212
Args:
@@ -15,7 +15,7 @@ def __init__(self, api_key: str, api_url: str = "https://api.anthropic.com/v1/me
1515
is_openrouter: 是否使用 OpenRouter API
1616
"""
1717
super().__init__(api_key, api_url)
18-
self.is_openrouter = is_openrouter
18+
self.provider = provider
1919

2020
async def stream_chat(self, messages: list, model: str = "claude-3-5-sonnet-20241022") -> AsyncGenerator[tuple[str, str], None]:
2121
"""流式对话
@@ -29,7 +29,8 @@ async def stream_chat(self, messages: list, model: str = "claude-3-5-sonnet-2024
2929
内容类型: "answer"
3030
内容: 实际的文本内容
3131
"""
32-
if self.is_openrouter:
32+
33+
if self.provider == "openrouter":
3334
logger.info("使用 OpenRouter API 作为 Claude 3.5 Sonnet 供应商 ")
3435
# 转换模型名称为 OpenRouter 格式
3536
model = "anthropic/claude-3.5-sonnet"
@@ -46,7 +47,19 @@ async def stream_chat(self, messages: list, model: str = "claude-3-5-sonnet-2024
4647
"messages": messages,
4748
"stream": True
4849
}
49-
else:
50+
elif self.provider == "oneapi":
51+
logger.info("使用 OneAPI API 作为 Claude 3.5 Sonnet 供应商 ")
52+
headers = {
53+
"Authorization": f"Bearer {self.api_key}",
54+
"Content-Type": "application/json"
55+
}
56+
57+
data = {
58+
"model": model,
59+
"messages": messages,
60+
"stream": True
61+
}
62+
elif self.provider == "anthropic":
5063
logger.info("使用 Anthropic API 作为 Claude 3.5 Sonnet 供应商 ")
5164
headers = {
5265
"x-api-key": self.api_key,
@@ -61,6 +74,8 @@ async def stream_chat(self, messages: list, model: str = "claude-3-5-sonnet-2024
6174
"max_tokens": 8192,
6275
"stream": True
6376
}
77+
else:
78+
raise ValueError(f"不支持的Claude Provider: {self.provider}")
6479

6580
async for chunk in self._make_request(headers, data):
6681
chunk_str = chunk.decode('utf-8')
@@ -75,16 +90,18 @@ async def stream_chat(self, messages: list, model: str = "claude-3-5-sonnet-2024
7590

7691
try:
7792
data = json.loads(json_str)
78-
if self.is_openrouter:
79-
# OpenRouter 格式
93+
if self.provider in ("openrouter", "oneapi"):
94+
# OpenRouter/OneApi 格式
8095
content = data.get('choices', [{}])[0].get('delta', {}).get('content', '')
8196
if content:
8297
yield "answer", content
83-
else:
98+
elif self.provider == "anthropic":
8499
# Anthropic 格式
85100
if data.get('type') == 'content_block_delta':
86101
content = data.get('delta', {}).get('text', '')
87102
if content:
88103
yield "answer", content
104+
else:
105+
raise ValueError(f"不支持的Claude Provider: {self.provider}")
89106
except json.JSONDecodeError:
90107
continue

app/deepclaude/deepclaude.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,15 +13,15 @@ class DeepClaude:
1313
def __init__(self, deepseek_api_key: str, claude_api_key: str,
1414
deepseek_api_url: str = "https://api.deepseek.com/v1/chat/completions",
1515
claude_api_url: str = "https://api.anthropic.com/v1/messages",
16-
is_openrouter: bool = False):
16+
claude_provider: str = "anthropic"):
1717
"""初始化 API 客户端
1818
1919
Args:
2020
deepseek_api_key: DeepSeek API密钥
2121
claude_api_key: Claude API密钥
2222
"""
2323
self.deepseek_client = DeepSeekClient(deepseek_api_key, deepseek_api_url)
24-
self.claude_client = ClaudeClient(claude_api_key, claude_api_url, is_openrouter)
24+
self.claude_client = ClaudeClient(claude_api_key, claude_api_url, claude_provider)
2525

2626
async def chat_completions_with_stream(self, messages: list,
2727
deepseek_model: str = "deepseek-reasoner",

app/main.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,8 @@
1616
# 从环境变量获取 API 密钥、地址以及模型名称
1717
CLAUDE_API_KEY = os.getenv("CLAUDE_API_KEY")
1818
CLAUDE_MODEL = os.getenv("CLAUDE_MODEL")
19-
USE_OPENROUTER = os.getenv("USE_OPENROUTER", "false").lower() == "true"
19+
# USE_OPENROUTER = os.getenv("USE_OPENROUTER", "false").lower() == "true"
20+
CLAUDE_PROVIDER = os.getenv("CLAUDE_PROVIDER", "anthropic") # Claude模型提供商, 默认为anthropic
2021
CLAUDE_API_URL = os.getenv("CLAUDE_API_URL", "https://api.anthropic.com/v1/messages")
2122

2223
DEEPSEEK_API_KEY = os.getenv("DEEPSEEK_API_KEY")
@@ -61,7 +62,7 @@ async def chat_completions(request: Request):
6162
CLAUDE_API_KEY,
6263
DEEPSEEK_API_URL,
6364
CLAUDE_API_URL,
64-
USE_OPENROUTER
65+
CLAUDE_PROVIDER
6566
)
6667

6768
# 4. 返回流式响应

0 commit comments

Comments
 (0)