Documentation Index
Fetch the complete documentation index at: https://docs.aihubmix.com/llms.txt
Use this file to discover all available pages before exploring further.
1. 핵심 통합 패턴
1.1 통합 인증 및 라우팅
// Core logic: Replace API Key, Base URL, add APP-Code
const config = {
apiKey: 'your-aihubmix-api-key', // Replace with aihubmix API Key
baseURL: 'https://aihubmix.com', // Replace with aihubmix gateway
headers: {
'APP-Code': 'App Code' // App Code can be obtained from https://aihubmix.com/appstore
}
};
// Model routing rules
function routeModel(modelName: string) {
if (modelName.startsWith('claude')) {
// Claude models: Use Anthropic SDK
return 'anthropic';
} else if (modelName.startsWith('gemini') && !modelName.endsWith('-nothink') && !modelName.endsWith('-search')) {
// Gemini models: Use Google SDK, endpoint https://aihubmix.com/gemini
return 'gemini';
} else {
// Other models: Use OpenAI compatible interface
return 'openai';
}
}
# Core logic: Replace API Key, Base URL, add APP-Code
credentials = {
"api_key": "your-aihubmix-api-key", # Replace with aihubmix API Key
"base_url": "https://aihubmix.com", # Replace with aihubmix gateway
"extra_headers": {
"APP-Code": "App Code" # App Code can be obtained from https://aihubmix.com/appstore
}
}
# Model routing rules
def route_model(model_name: str):
if model_name.startswith("claude"):
# Claude models: Use Anthropic SDK
return "anthropic"
elif model_name.startswith("gemini") and not model_name.endswith(("-nothink", "-search")):
# Gemini models: Use Google SDK, endpoint https://aihubmix.com/gemini
return "gemini"
else:
# Other models: Use OpenAI compatible interface
return "openai"
1.2 특수 처리 사항
- 빈 Tools 수정:
tools=[]이고 tool_choice가 존재하는 경우 자동으로 tool_choice 제거
- 파일 확장자:
mediaType에 따라 올바른 파일 확장자 자동 설정
- 캐시 제어:
<cache> 태그를 통한 캐시 제어 지원
2. 통합 구현
2.1 핵심 클라이언트 래퍼
class AihubmixModelClient {
private config: {
apiKey: string;
baseURL: string;
appCode: string;
};
constructor(apiKey: string) {
this.config = {
apiKey,
baseURL: 'https://aihubmix.com',
appCode: 'App Code can be obtained from https://aihubmix.com/appstore'
};
}
async chatCompletion(model: string, messages: any[], options: any = {}) {
// Automatically route to corresponding SDK based on model name
if (model.startsWith('claude')) {
return this.claudeCompletion(model, messages, options);
} else if (model.startsWith('gemini')) {
return this.geminiCompletion(model, messages, options);
} else {
return this.openaiCompletion(model, messages, options);
}
}
private async claudeCompletion(model: string, messages: any[], options: any) {
const { Anthropic } = await import('@anthropic-ai/sdk');
const client = new Anthropic({
apiKey: this.config.apiKey,
baseURL: this.config.baseURL,
defaultHeaders: { 'APP-Code': this.config.appCode }
});
return client.messages.create({ model, messages, ...options });
}
private async geminiCompletion(model: string, messages: any[], options: any) {
const { GoogleGenerativeAI } = await import('@google/generative-ai');
const genAI = new GoogleGenerativeAI(this.config.apiKey, {
baseURL: `${this.config.baseURL}/gemini/v1beta`,
defaultHeaders: { 'APP-Code': this.config.appCode }
});
const genModel = genAI.getGenerativeModel({ model });
return genModel.generateContent(messages);
}
private async openaiCompletion(model: string, messages: any[], options: any) {
const OpenAI = await import('openai');
const client = new OpenAI.default({
apiKey: this.config.apiKey,
baseURL: `${this.config.baseURL}/v1`,
defaultHeaders: { 'APP-Code': this.config.appCode }
});
return client.chat.completions.create({ model, messages, ...options });
}
}
// Usage example
const client = new AihubmixModelClient('your-aihubmix-api-key');
await client.chatCompletion('gpt-4o-mini', messages);
await client.chatCompletion('claude-3-5-sonnet-20241022', messages);
await client.chatCompletion('gemini-2.5-flash', messages);
class AihubmixModelClient:
def __init__(self, api_key: str):
self.api_key = api_key
self.base_url = "https://aihubmix.com"
self.headers = {
"Authorization": f"Bearer {api_key}",
"APP-Code": "App Code can be obtained from https://aihubmix.com/appstore"
}
def chat_completion(self, model: str, messages: list, **kwargs):
"""Unified chat completion interface"""
if model.startswith("claude"):
return self._claude_completion(model, messages, **kwargs)
elif model.startswith("gemini"):
return self._gemini_completion(model, messages, **kwargs)
else:
return self._openai_completion(model, messages, **kwargs)
def _claude_completion(self, model: str, messages: list, **kwargs):
import anthropic
client = anthropic.Anthropic(
api_key=self.api_key,
base_url=self.base_url,
extra_headers={"APP-Code": "App Code can be obtained from https://aihubmix.com/appstore"}
)
return client.messages.create(model=model, messages=messages, **kwargs)
def _gemini_completion(self, model: str, messages: list, **kwargs):
import google.generativeai as genai
genai.configure(
api_key=self.api_key,
client_options={"api_endpoint": f"{self.base_url}/gemini/v1beta"}
)
genai._client._http_client._session.headers.update({"APP-Code": "App Code can be obtained from https://aihubmix.com/appstore"})
model_instance = genai.GenerativeModel(model)
return model_instance.generate_content(messages)
def _openai_completion(self, model: str, messages: list, **kwargs):
import openai
client = openai.OpenAI(
api_key=self.api_key,
base_url=f"{self.base_url}/v1",
extra_headers={"APP-Code": "App Code can be obtained from https://aihubmix.com/appstore"}
)
return client.chat.completions.create(model=model, messages=messages, **kwargs)
# Usage example
client = AihubmixModelClient("your-aihubmix-api-key")
await client.chat_completion("gpt-4o-mini", messages)
await client.chat_completion("claude-3-5-sonnet-20241022", messages)
await client.chat_completion("gemini-2.5-flash", messages)
2.2 특수 처리 및 유틸리티 함수
// Empty tools fix
function fixToolChoice(requestBody: any): any {
if (requestBody.tools?.length === 0 && requestBody.tool_choice) {
delete requestBody.tool_choice;
}
return requestBody;
}
// File extension mapping
function setFileExtension(mediaType: string): string {
const mimeToExt: Record<string, string> = {
'audio/mpeg': 'mp3', 'audio/wav': 'wav', 'audio/flac': 'flac'
};
return mimeToExt[mediaType] || 'bin';
}
// Cache control
function processCacheTags(content: string): { content: string; cacheControl?: any } {
if (content.includes('<cache>')) {
return { content: content.replace('<cache>', ''), cacheControl: { type: 'ephemeral' } };
}
return { content };
}
# Empty tools fix
def fix_tool_choice(request_body: dict) -> dict:
if request_body.get("tools") == [] and "tool_choice" in request_body:
del request_body["tool_choice"]
return request_body
# File extension mapping
def set_file_extension(media_type: str) -> str:
mime_to_ext = {
'audio/mpeg': 'mp3', 'audio/wav': 'wav', 'audio/flac': 'flac'
}
return mime_to_ext.get(media_type, 'bin')
# Cache control
def process_cache_tags(content: str):
if "<cache>" in content:
return {
"content": content.replace("<cache>", ""),
"cache_control": {"type": "ephemeral"}
}
return {"content": content}
3. 배포 및 구성
3.1 환경 변수
const config = {
apiKey: process.env.AIHUBMIX_API_KEY || '',
baseURL: process.env.AIHUBMIX_BASE_URL || 'https://aihubmix.com',
appCode: process.env.AIHUBMIX_APP_CODE || 'App Code can be obtained from https://aihubmix.com/appstore'
};
import os
config = {
"api_key": os.getenv("AIHUBMIX_API_KEY", ""),
"base_url": os.getenv("AIHUBMIX_BASE_URL", "https://aihubmix.com"),
"app_code": os.getenv("AIHUBMIX_APP_CODE", "App Code can be obtained from https://aihubmix.com/appstore")
}
3.2 오류 처리
class AihubmixError extends Error {
constructor(message: string, public code?: string, public status?: number) {
super(message);
this.name = 'AihubmixError';
}
}
function handleAihubmixErrors(error: any): AihubmixError {
const message = error.message || 'Unknown error';
if (message.toLowerCase().includes('rate limit')) {
return new AihubmixError('Rate limit exceeded', 'RATE_LIMIT', 429);
} else if (message.toLowerCase().includes('unauthorized')) {
return new AihubmixError('Authentication failed', 'AUTH_ERROR', 401);
} else {
return new AihubmixError(message, error.code, error.status);
}
}
class AihubmixError(Exception):
def __init__(self, message: str, code: str = None, status: int = None):
super().__init__(message)
self.code = code
self.status = status
def handle_aihubmix_errors(e: Exception) -> AihubmixError:
message = str(e).lower()
if "rate limit" in message:
return AihubmixError("Rate limit exceeded", "RATE_LIMIT", 429)
elif "unauthorized" in message:
return AihubmixError("Authentication failed", "AUTH_ERROR", 401)
else:
return AihubmixError(f"Request failed: {e}")
4. 참조 구현 및 정합성 체크리스트
4.1 cherry-studio 클라이언트 참조 (TypeScript)
cherry-studio의 AihubmixAPIClient.ts의 다음 핵심 요점은 TypeScript 측에서 aihubmix와 통합하는 써드파티 프론트엔드/데스크톱 애플리케이션의 적용 패턴으로 사용할 수 있습니다:
- 통합 할인 코드 추가: Provider 수준에서
extra_headers를 병합하고 APP-Code를 설정 (프로젝트에서 MLTG2087 사용)
- 다중 클라이언트 라우팅:
claude* → Anthropic 클라이언트 사용
-nothink/-search로 끝나지 않고 embedding을 포함하지 않는 gemini*/imagen* → Gemini 클라이언트 사용 (apiHost: https://aihubmix.com/gemini)
- OpenAI 시리즈 (
gpt-oss 제외) → OpenAI 호환 response 클라이언트 사용
- 기타 → 기본 OpenAI 클라이언트로 대체
- BaseURL 검색: 현재 라우팅된 특정 클라이언트에서 내보내, 각 공급자에 대한 엔드포인트 차이 유지
4.2 dify-plugin-aihubmix 참조 (Python)
dify-plugin-aihubmix 구현의 다음 핵심 요점은 Python 도구가 aihubmix와 통합하는 써드파티의 적용 패턴으로 사용할 수 있습니다:
- 통합 할인 코드 추가: Provider 수준에서
extra_headers를 병합하고 APP-Code를 설정 (프로젝트에서 Dify2025 사용)
- 다중 클라이언트 라우팅:
claude* → Anthropic 클라이언트 사용
-nothink/-search로 끝나지 않고 embedding을 포함하지 않는 gemini*/imagen* → Gemini 클라이언트 사용 (apiHost: https://aihubmix.com/gemini)
- OpenAI 시리즈 (
gpt-oss 제외) → OpenAI 호환 response 클라이언트 사용
- 기타 → 기본 OpenAI 클라이언트로 대체
- BaseURL 검색: 현재 라우팅된 특정 클라이언트에서 내보내, 각 공급자에 대한 엔드포인트 차이 유지
4.3 정합성 체크리스트
- Provider 진입점에서
extra_headers를 통합 병합하고 APP-Code를 주입
- Gemini 클라이언트는
https://aihubmix.com/gemini를 apiHost로 사용
claude*, gemini*/imagen*, OpenAI 시리즈 (gpt-oss 제외)와 일치하는 라우팅 규칙
- 기본적으로 OpenAI 클라이언트로 대체하여, OpenAI 호환 인터페이스 동작 유지
getBaseURL()은 항상 현재 라우팅된 클라이언트에서 내보내어 하드코딩 방지
5. 마이그레이션 체크리스트
- API Key를 aihubmix API Key로 교체
- Base URL을
https://aihubmix.com로 교체
- 할인을 위해
APP-Code 헤더 추가
- 모델 라우팅 로직 구현 (claude/gemini/openai)
- tools가 비어 있을 때
tool_choice 수정 처리
- 파일 업로드를 위한 MIME 타입 처리 구성
- 다양한 모델 호출 테스트
마지막 업데이트: 2026-06-01