| # -*- coding: utf-8 -*- | |
| """ | |
| Darwin-60B-DUO Gateway — FastAPI OpenAI-compatible orchestrator. | |
| Exposes a single OpenAI-compatible endpoint ("darwin-60b-duo") that | |
| internally routes to two backends: | |
| - Darwin-28B-REASON (English reasoning specialist, HF GPQA Diamond #3) | |
| - AWAXIS-Think-31B (Korean specialist, K-AI Leaderboard #1) | |
| Hybrid-A strategy (config.json): | |
| - 70% Route (single backend) | |
| - 20% Split / Refine (sequential two-model collaboration) | |
| - 10% Ensemble V_1 (cross-verification tournament for MCQ / short answers) | |
| Run: | |
| pip install -r requirements.txt | |
| python server.py --port 8000 \\ | |
| --darwin-url http://127.0.0.1:8021/v1 \\ | |
| --awaxis-url http://127.0.0.1:8022/v1 | |
| License: Gemma (combined-license inheritance — see README). | |
| """ | |
| import argparse | |
| import asyncio | |
| import json | |
| import time | |
| import uuid | |
| from typing import Any, Dict, List, Optional | |
| import httpx | |
| from fastapi import FastAPI, HTTPException | |
| from fastapi.responses import JSONResponse, StreamingResponse | |
| from pydantic import BaseModel, Field | |
| from router import select_strategy, RouteDecision | |
| from refine import sequential_refine | |
| from ensemble import ensemble_v1 | |
| # --------------------------------------------------------------------------- | |
| # Pydantic models — OpenAI Chat Completions API subset | |
| # --------------------------------------------------------------------------- | |
| class ChatMessage(BaseModel): | |
| role: str | |
| content: str | |
| class ChatCompletionRequest(BaseModel): | |
| model: str = "darwin-60b-duo" | |
| messages: List[ChatMessage] | |
| temperature: float = 0.7 | |
| top_p: float = 0.95 | |
| max_tokens: int = 4096 | |
| n: int = 1 | |
| stream: bool = False | |
| # Optional: force a specific strategy ("route_darwin", "route_awaxis", | |
| # "split_refine", "ensemble_v1", "auto"). Default "auto" = Hybrid-A router. | |
| duo_strategy: Optional[str] = "auto" | |
| # --------------------------------------------------------------------------- | |
| # Backend HTTP client | |
| # --------------------------------------------------------------------------- | |
| class Backend: | |
| def __init__(self, name: str, base_url: str, served_name: str): | |
| self.name = name | |
| self.base_url = base_url.rstrip("/") | |
| self.served_name = served_name | |
| self.client = httpx.AsyncClient(timeout=httpx.Timeout(900.0)) | |
| async def chat( | |
| self, | |
| messages: List[Dict[str, str]], | |
| temperature: float = 0.7, | |
| max_tokens: int = 4096, | |
| n: int = 1, | |
| top_p: float = 0.95, | |
| ) -> List[str]: | |
| payload = { | |
| "model": self.served_name, | |
| "messages": messages, | |
| "temperature": temperature, | |
| "top_p": top_p, | |
| "max_tokens": max_tokens, | |
| "n": n, | |
| } | |
| r = await self.client.post( | |
| f"{self.base_url}/chat/completions", json=payload | |
| ) | |
| r.raise_for_status() | |
| data = r.json() | |
| return [c["message"]["content"] for c in data["choices"]] | |
| async def health(self) -> bool: | |
| try: | |
| r = await self.client.get(f"{self.base_url}/models", timeout=5) | |
| return r.status_code == 200 | |
| except Exception: | |
| return False | |
| # --------------------------------------------------------------------------- | |
| # FastAPI app | |
| # --------------------------------------------------------------------------- | |
| app = FastAPI( | |
| title="Darwin-60B-DUO Gateway", | |
| version="1.0.0", | |
| description=( | |
| "Single OpenAI-compatible endpoint for the Darwin-60B-DUO " | |
| "(Darwin-28B-REASON + AWAXIS-Think-31B). Hybrid-A routing." | |
| ), | |
| ) | |
| # Initialized via CLI args at startup | |
| DARWIN: Optional[Backend] = None | |
| AWAXIS: Optional[Backend] = None | |
| async def list_models(): | |
| """Expose only the aggregate model to external callers.""" | |
| return { | |
| "object": "list", | |
| "data": [ | |
| { | |
| "id": "darwin-60b-duo", | |
| "object": "model", | |
| "owned_by": "FINAL-Bench", | |
| "created": int(time.time()), | |
| } | |
| ], | |
| } | |
| async def health(): | |
| d_ok = await DARWIN.health() if DARWIN else False | |
| a_ok = await AWAXIS.health() if AWAXIS else False | |
| status = "ok" if (d_ok and a_ok) else "degraded" | |
| return { | |
| "status": status, | |
| "backends": { | |
| "darwin-28r": d_ok, | |
| "awaxis-31b": a_ok, | |
| }, | |
| "gateway_version": "1.0.0", | |
| } | |
| def _build_response(content: str, route_meta: Dict[str, Any]) -> Dict[str, Any]: | |
| """Build an OpenAI-compatible Chat Completion response with route metadata.""" | |
| return { | |
| "id": f"chatcmpl-{uuid.uuid4().hex[:24]}", | |
| "object": "chat.completion", | |
| "created": int(time.time()), | |
| "model": "darwin-60b-duo", | |
| "choices": [ | |
| { | |
| "index": 0, | |
| "message": { | |
| "role": "assistant", | |
| "content": content, | |
| }, | |
| "finish_reason": "stop", | |
| } | |
| ], | |
| "usage": { | |
| "prompt_tokens": -1, # Aggregate gateway does not track tokens | |
| "completion_tokens": -1, | |
| "total_tokens": -1, | |
| }, | |
| # Non-standard metadata for transparency / debugging | |
| "_duo_route": route_meta, | |
| } | |
| async def chat_completions(req: ChatCompletionRequest): | |
| if not req.messages: | |
| raise HTTPException(400, "messages must not be empty") | |
| user_text = req.messages[-1].content | |
| messages_dict = [m.dict() for m in req.messages] | |
| # ----- Strategy selection ----- | |
| if req.duo_strategy and req.duo_strategy != "auto": | |
| decision = RouteDecision(strategy=req.duo_strategy, reason="user_forced") | |
| else: | |
| decision = select_strategy(user_text) | |
| t0 = time.time() | |
| # ----- Execute ----- | |
| try: | |
| if decision.strategy == "route_darwin": | |
| outputs = await DARWIN.chat( | |
| messages_dict, | |
| temperature=req.temperature, | |
| max_tokens=req.max_tokens, | |
| top_p=req.top_p, | |
| ) | |
| content = outputs[0] | |
| elif decision.strategy == "route_awaxis": | |
| outputs = await AWAXIS.chat( | |
| messages_dict, | |
| temperature=req.temperature, | |
| max_tokens=req.max_tokens, | |
| top_p=req.top_p, | |
| ) | |
| content = outputs[0] | |
| elif decision.strategy == "split_refine": | |
| # Darwin reasons in English → AWAXIS polishes in Korean | |
| content = await sequential_refine( | |
| DARWIN, AWAXIS, messages_dict, | |
| temperature=req.temperature, max_tokens=req.max_tokens | |
| ) | |
| elif decision.strategy == "split_refine_reverse": | |
| # AWAXIS retrieves Korean context → Darwin polishes in English | |
| content = await sequential_refine( | |
| AWAXIS, DARWIN, messages_dict, | |
| temperature=req.temperature, max_tokens=req.max_tokens | |
| ) | |
| elif decision.strategy == "ensemble_v1": | |
| # MCQ / short answer: MAJ@N per model + cross-verify if mismatched | |
| content = await ensemble_v1( | |
| DARWIN, AWAXIS, messages_dict, | |
| temperature=req.temperature, max_tokens=req.max_tokens, | |
| n_rsa=8, | |
| ) | |
| else: | |
| # Fallback: AWAXIS (default for ambiguous / mixed) | |
| outputs = await AWAXIS.chat( | |
| messages_dict, temperature=req.temperature, | |
| max_tokens=req.max_tokens, top_p=req.top_p, | |
| ) | |
| content = outputs[0] | |
| decision.strategy = "fallback_awaxis" | |
| except httpx.HTTPError as e: | |
| raise HTTPException(503, f"backend error: {type(e).__name__}: {e}") | |
| elapsed = time.time() - t0 | |
| route_meta = { | |
| "strategy": decision.strategy, | |
| "reason": decision.reason, | |
| "elapsed_s": round(elapsed, 2), | |
| "language_ratio": decision.korean_ratio, | |
| } | |
| return JSONResponse(_build_response(content, route_meta)) | |
| # --------------------------------------------------------------------------- | |
| # CLI | |
| # --------------------------------------------------------------------------- | |
| def main(): | |
| p = argparse.ArgumentParser() | |
| p.add_argument("--host", default="0.0.0.0") | |
| p.add_argument("--port", type=int, default=8000) | |
| p.add_argument( | |
| "--darwin-url", default="http://127.0.0.1:8021/v1", | |
| help="Darwin-28B-REASON vLLM endpoint", | |
| ) | |
| p.add_argument( | |
| "--awaxis-url", default="http://127.0.0.1:8022/v1", | |
| help="AWAXIS-Think-31B vLLM endpoint", | |
| ) | |
| p.add_argument("--darwin-served-name", default="darwin-28r") | |
| p.add_argument("--awaxis-served-name", default="awaxis-31b") | |
| args = p.parse_args() | |
| global DARWIN, AWAXIS | |
| DARWIN = Backend("darwin-28r", args.darwin_url, args.darwin_served_name) | |
| AWAXIS = Backend("awaxis-31b", args.awaxis_url, args.awaxis_served_name) | |
| import uvicorn | |
| uvicorn.run(app, host=args.host, port=args.port, log_level="info") | |
| if __name__ == "__main__": | |
| main() | |
Xet Storage Details
- Size:
- 9.2 kB
- Xet hash:
- c40dab8c22f11468997b312d43f344ca8afeb532281b886697d7662516fd0875
·
Xet efficiently stores files, intelligently splitting them into unique chunks and accelerating uploads and downloads. More info.