{"id":50531901,"url":"https://github.com/timcsy/ai-api","last_synced_at":"2026-06-03T14:30:37.570Z","repository":{"id":361077592,"uuid":"1245807761","full_name":"timcsy/ai-api","owner":"timcsy","description":"Self-hosted, OpenAI-compatible AI gateway for organizations — multi-provider (Azure/OpenAI/Anthropic/Gemini), revocable per-allocation credentials, usage \u0026 cost tracking, and an OpenAI Codex–ready /v1/responses endpoint.","archived":false,"fork":false,"pushed_at":"2026-05-29T04:37:08.000Z","size":1722,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-05-29T06:21:11.321Z","etag":null,"topics":["ai-gateway","anthropic","api-gateway","azure-openai","fastapi","gemini","helm","kubernetes","litellm","llm-gateway","openai-codex","openai-compatible","react","responses-api","self-hosted","usage-tracking"],"latest_commit_sha":null,"homepage":"https://ai-ccsh.tew.tw/","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/timcsy.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":"AGENTS.md","dco":null,"cla":null}},"created_at":"2026-05-21T15:18:39.000Z","updated_at":"2026-05-29T05:36:19.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/timcsy/ai-api","commit_stats":null,"previous_names":["timcsy/ai-api"],"tags_count":null,"template":false,"template_full_name":null,"purl":"pkg:github/timcsy/ai-api","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/timcsy%2Fai-api","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/timcsy%2Fai-api/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/timcsy%2Fai-api/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/timcsy%2Fai-api/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/timcsy","download_url":"https://codeload.github.com/timcsy/ai-api/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/timcsy%2Fai-api/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":33870025,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-03T02:00:06.370Z","response_time":59,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["ai-gateway","anthropic","api-gateway","azure-openai","fastapi","gemini","helm","kubernetes","litellm","llm-gateway","openai-codex","openai-compatible","react","responses-api","self-hosted","usage-tracking"],"created_at":"2026-06-03T14:30:36.802Z","updated_at":"2026-06-03T14:30:37.562Z","avatar_url":"https://github.com/timcsy.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# AI API Manager\n\n[![CI](https://github.com/timcsy/ai-api/actions/workflows/ci.yml/badge.svg)](https://github.com/timcsy/ai-api/actions/workflows/ci.yml)\n[![Frontend CI](https://github.com/timcsy/ai-api/actions/workflows/frontend.yml/badge.svg)](https://github.com/timcsy/ai-api/actions/workflows/frontend.yml)\n[![Image build](https://github.com/timcsy/ai-api/actions/workflows/image.yml/badge.svg)](https://github.com/timcsy/ai-api/actions/workflows/image.yml)\n![Python](https://img.shields.io/badge/python-3.11%2B-blue)\n![React](https://img.shields.io/badge/react-19-61dafb)\n![runtime](https://img.shields.io/badge/runtime-distroless-0b7285)\n[![License: MIT](https://img.shields.io/badge/license-MIT-green)](./LICENSE)\n\n組織內部 AI API 的**單一分流入口**：用一套 OpenAI 相容的閘道，把多家 AI 供應商\n（Azure OpenAI / OpenAI / Anthropic / Gemini）統一對成員開放，並以**可撤回的分配憑證**\n管控誰能用、用多少、花多少——用量與成本全部統一歸戶。\n\n\u003e 核心理念：**分享就是資源的分配**。每一筆 AI 存取都是一份有對象、有額度、可調整、\n\u003e 可收回的資源，而不是一次性把 key 發出去。\n\n## 功能總覽\n\n- **OpenAI 相容代理**\n  - `POST /v1/chat/completions`（Chat Completions）\n  - `POST /v1/responses`（Responses API，**支援 SSE streaming、工具呼叫、reasoning**）\n    — 讓 **OpenAI Codex** 等 agent CLI 用平台憑證即可使用\n- **多供應商**：經 `litellm`（library form）統一抽象；OpenAI/Azure 原生高保真、其他家自動橋接\n- **可撤回分配憑證**：每筆分配發行獨立 token；撤回後即時生效（不等過期），也可**暫停 / 恢復**\n- **身份與成員管理**：Google Workspace SSO + 本機密碼；白名單 / 自動註冊規則 / 來源限制\n- **模型目錄**：以「模型」為第一公民，多面向 filter；可見性 = 已配置 credential ∩ 存取政策\n- **Tag-based 存取規則**：用 tag 批次授權；新成員可依規則自動貼 tag\n- **自助領取憑證**：被授權的成員可對開放的 model 一鍵領取；亦可自助暫停/恢復自己的憑證\n- **用量觀測與計費**：point-in-time 計費，分項記錄 input / output / **reasoning / cached** token；\n  月度配額、自適應配額池、CSV/JSON 匯出\n- **管理員 Web UI**：成員、分配、用量、配額、價目、Provider 憑證、稽核紀錄\n- **安全加固**：Provider key 以 Fernet 加密落 DB（金鑰由 K8s Secret 提供，pod 啟動即驗證）、\n  K8s NetworkPolicy、CI Trivy 掃描 + SBOM、distroless runtime\n\n## 架構\n\n```mermaid\nflowchart TD\n    Codex[\"OpenAI Codex CLI\"] --\u003e|Bearer token| NG\n    SDK[\"curl / OpenAI SDK\"] --\u003e|Bearer token| NG\n    Admin[\"管理員 / 成員瀏覽器\"] --\u003e|session cookie| NG\n    NG[\"nginx（單一來源反向代理）\"] --\u003e API\n\n    subgraph GW[\"FastAPI Gateway\"]\n        API[\"API 路由\u003cbr/\u003e/v1/responses · /v1/chat/completions\u003cbr/\u003e/admin · /me · /catalog\"]\n        PF[\"共用 preflight\u003cbr/\u003e憑證 → 分配狀態 → 配額 → model binding → 存取政策\"]\n        UP[\"litellm（library form）\"]\n        REC[\"計費 + 用量記錄\"]\n        API --\u003e PF --\u003e UP\n        API --\u003e REC\n    end\n\n    UP --\u003e AZ[\"Azure OpenAI\"]\n    UP --\u003e OA[\"OpenAI\"]\n    UP --\u003e AN[\"Anthropic\"]\n    UP --\u003e GE[\"Gemini\"]\n\n    GW --\u003e DB[(\"PostgreSQL\u003cbr/\u003emembers · allocations · credentials\u003cbr/\u003ecall_records · price_list\u003cbr/\u003estored_responses · model_catalog\")]\n```\n\n- **後端**：FastAPI（Python 3.11+）+ SQLAlchemy 2.x async + Alembic；上游經 `litellm` library form\n- **前端**：React 19 + Vite 6 + TypeScript（strict）+ shadcn/ui + TanStack Query\n- **資料庫**：PostgreSQL（生產）/ SQLite（dev、CI）\n- **部署**：Kubernetes + Helm chart（`deploy/helm/ai-api`）；前端為單一來源 nginx 反向代理到後端\n- **映像**：後端 distroless、前端 unprivileged nginx；CI 以 GitHub Actions build + Trivy 把關\n\n## 對外 API\n\n把 `$TOKEN` 換成你分配到的憑證，放在 `Authorization: Bearer`。\n\n```bash\n# Chat Completions\ncurl -X POST https://\u003chost\u003e/v1/chat/completions \\\n  -H \"Authorization: Bearer $TOKEN\" -H \"Content-Type: application/json\" \\\n  -d '{\"model\":\"azure/gpt-4o\",\"messages\":[{\"role\":\"user\",\"content\":\"你好\"}]}'\n\n# Responses（含串流）\ncurl -N -X POST https://\u003chost\u003e/v1/responses \\\n  -H \"Authorization: Bearer $TOKEN\" -H \"Content-Type: application/json\" \\\n  -d '{\"model\":\"azure/gpt-5.4\",\"input\":\"你好\",\"stream\":true}'\n```\n\n### 搭配 OpenAI Codex\n\n支援 `responses` 能力的模型可在後台「模型目錄 → 如何呼叫 → Codex」分頁**下載 `config.toml`**\n並依各作業系統步驟設定。基本設定：\n\n```toml\n# ~/.codex/config.toml\nmodel = \"azure/gpt-5.4\"\nmodel_provider = \"gateway\"\n\n[model_providers.gateway]\nname = \"AI Gateway\"\nbase_url = \"https://\u003chost\u003e/v1\"\nwire_api = \"responses\"\nenv_key = \"AIAPI_TOKEN\"\n```\n\n```bash\nexport AIAPI_TOKEN=\"$TOKEN\"\ncodex \"在這個資料夾建一個 hello.py 並執行\"\n```\n\n## 本機開發\n\n需要 Python 3.11+、[uv](https://github.com/astral-sh/uv)、Node.js（前端）、一個 Postgres。\n\n```bash\n# 後端\nexport DATABASE_URL=postgresql+asyncpg://aiapi:aiapi@localhost:5432/aiapi\nuv sync\nuv run alembic upgrade head\nuv run uvicorn ai_api.main:app --reload --port 8000\n\n# 前端（另一個終端）\ncd frontend\nnpm install\nnpm run dev\n```\n\n詳細環境變數與首位管理員設定見 [`docs/deployment.md`](./docs/deployment.md)。\n\n## 測試與檢查\n\n```bash\n# 後端：單元 + 契約（Docker-free，in-memory/temp SQLite）\nuv run pytest tests/unit tests/contract\nuv run pytest            # 含整合測試（需 Docker / Postgres）\nuv run ruff check . \u0026\u0026 uv run mypy src/ai_api\n\n# 前端\ncd frontend \u0026\u0026 npm run lint \u0026\u0026 npm run typecheck \u0026\u0026 npm test\n```\n\n## 部署\n\nKubernetes / Helm 部署、必填機密、首位管理員 bootstrap、Responses/Codex 與 SSE 不緩衝\n等注意事項，詳見 [`docs/deployment.md`](./docs/deployment.md)。\n\n## 文件\n\n- 工程憲章：[`.specify/memory/constitution.md`](./.specify/memory/constitution.md)\n- 領域原則：[`knowledge/principles.md`](./knowledge/principles.md)\n- 願景與路線圖：[`knowledge/vision.md`](./knowledge/vision.md)\n- 經驗教訓：[`knowledge/experience.md`](./knowledge/experience.md)\n- 設計文件：[`knowledge/design/`](./knowledge/design/)\n- 功能規格（spec / plan / tasks）：[`specs/`](./specs/)\n- 部署指南：[`docs/deployment.md`](./docs/deployment.md)\n\n## 開發流程\n\n本專案採 spec-driven 開發（spec → plan → tasks → 失敗測試 → 實作 → 重構 → 審查 → 合併），\n並強制 TDD 與契約優先；規格文件一律繁體中文、程式識別字英文。詳見工程憲章。\n\n## 授權\n\n[MIT License](./LICENSE)。\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftimcsy%2Fai-api","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ftimcsy%2Fai-api","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftimcsy%2Fai-api/lists"}