192 lines
5.1 KiB
Markdown
192 lines
5.1 KiB
Markdown
# optoant — LLM Gateway
|
||
|
||
Go + Fiber v3 tabanlı OpenAI-uyumlu ve Anthropic-uyumlu LLM proxy/gateway. DeepSeek gibi tek upstream backend üzerinden hem OpenAI (`/v1/*`) hem Anthropic (`/anthropic/*`) API sunar. Anthropic↔OpenAI dönüşümü built-in. PostgreSQL request loglama, Swagger UI ve Docker desteği ile birlikte gelir.
|
||
|
||
## Özellikler
|
||
|
||
- **OpenAI-uyumlu proxy**: `/v1/*` → `OPENAI_BACKEND` (direct passthrough)
|
||
- **Anthropic-uyumlu proxy**: `/anthropic/*` → Anthropic↔OpenAI dönüşümü → `OPENAI_BACKEND`
|
||
- **Built-in dönüşüm**: Anthropic Messages ↔ OpenAI Chat Completions format çevrimi
|
||
- **PostgreSQL loglama**: Her isteği GORM ile otomatik loglar
|
||
- **Swagger UI**: `/swagger/*` adresinde erişilebilir
|
||
- **Docker**: Multi-stage build + docker-compose
|
||
- **Konfigürasyon**: Sadece 4 env değişkeni
|
||
|
||
---
|
||
|
||
## Hızlı Başlangıç
|
||
|
||
### 1. Bağımlılıkları Kur
|
||
|
||
```bash
|
||
go mod download
|
||
```
|
||
|
||
### 2. Ortam Değişkenlerini Ayarla
|
||
|
||
```bash
|
||
cp .env.example .env
|
||
# .env dosyasını düzenle
|
||
```
|
||
|
||
Minimum `.env`:
|
||
```env
|
||
PORT=8000
|
||
OPENAI_BACKEND=https://api.deepseek.com
|
||
DATABASE_DSN=postgres://user:pass@localhost:5432/optoant?sslmode=disable
|
||
REQUEST_TIMEOUT_SECONDS=30
|
||
```
|
||
|
||
### 3. Çalıştır
|
||
|
||
```bash
|
||
go run main.go
|
||
```
|
||
|
||
veya derleyip çalıştır:
|
||
|
||
```bash
|
||
go build -o gateway ./main.go
|
||
./gateway
|
||
```
|
||
|
||
---
|
||
|
||
## Docker ile Çalıştırma
|
||
|
||
```bash
|
||
# Sadece uygulamayı derle
|
||
docker build -t optoant-gateway:latest -f docker/Dockerfile .
|
||
|
||
# Postgres dahil tüm stack'i ayağa kaldır
|
||
cd docker
|
||
docker-compose up -d
|
||
```
|
||
|
||
---
|
||
|
||
## Konfigürasyon Tablosu
|
||
|
||
| Değişken | Varsayılan | Açıklama |
|
||
|----------|-----------|----------|
|
||
| `PORT` | `8000` | Dinleme portu |
|
||
| `OPENAI_BACKEND` | `https://api.deepseek.com` | Upstream backend (OpenAI ve Anthropic için ortak) |
|
||
| `DATABASE_DSN` veya `POSTGRES_DSN` | — | PostgreSQL bağlantı string'i |
|
||
| `REQUEST_TIMEOUT_SECONDS` | `30` | Upstream timeout (saniye) |
|
||
|
||
---
|
||
|
||
## Endpoint'ler
|
||
|
||
| Endpoint | Method | Açıklama |
|
||
|----------|--------|----------|
|
||
| `/v1/*` | ANY | OpenAI-uyumlu proxy |
|
||
| `/anthropic/*` | ANY | Anthropic-uyumlu proxy (Anthropic↔OpenAI dönüşümlü) |
|
||
| `/health` | GET | Sağlık kontrolü |
|
||
| `/swagger/*` | GET | Swagger UI |
|
||
|
||
---
|
||
|
||
## Örnek curl Çağrıları
|
||
|
||
### OpenAI-uyumlu (DeepSeek / Bifrost OpenAI)
|
||
|
||
```bash
|
||
curl -X POST "http://localhost:8000/v1/chat/completions" \
|
||
-H "Authorization: Bearer $OPENAI_KEY" \
|
||
-H "Content-Type: application/json" \
|
||
-d '{
|
||
"model": "gpt-4",
|
||
"messages": [{"role": "user", "content": "Hello!"}]
|
||
}'
|
||
```
|
||
|
||
### Anthropic (Anthropic↔OpenAI dönüşümlü)
|
||
|
||
```bash
|
||
curl -X POST "http://localhost:8000/anthropic/v1/messages" \
|
||
-H "Authorization: Bearer $ANTHROPIC_KEY" \
|
||
-H "Content-Type: application/json" \
|
||
-d '{
|
||
"model": "claude-3-5-sonnet-20241022",
|
||
"max_tokens": 1024,
|
||
"messages": [{"role": "user", "content": "Hello!"}]
|
||
}'
|
||
```
|
||
|
||
### Sağlık kontrolü
|
||
|
||
```bash
|
||
curl http://localhost:8000/health
|
||
```
|
||
|
||
---
|
||
|
||
## Testler
|
||
|
||
```bash
|
||
go test ./tests/...
|
||
```
|
||
|
||
---
|
||
|
||
## Proje Yapısı
|
||
|
||
```
|
||
opantoantro/
|
||
├── main.go # Fiber app, DB, route kayıt
|
||
├── config/config.go # Env yükleme
|
||
├── handlers/
|
||
│ ├── openai.go # /v1/* handler
|
||
│ ├── anthropic.go # /anthropic/* handler
|
||
│ └── health.go # /health handler
|
||
├── internal/
|
||
│ ├── proxy/proxy.go # Generic HTTP forwarder
|
||
│ └── transform/anthropic_bifrost.go # Format dönüşümleri
|
||
├── models/request_log.go # GORM modeli
|
||
├── docs/
|
||
│ ├── swagger.json # Swagger spec
|
||
│ └── wiki/ # Obsidian knowledge graph
|
||
│ ├── Index.md
|
||
│ ├── Config.md
|
||
│ ├── Proxy.md
|
||
│ ├── Handlers.md
|
||
│ └── Models_Transform.md
|
||
├── tests/openai_test.go # Unit testler
|
||
├── docker/
|
||
│ ├── Dockerfile # Multi-stage build
|
||
│ └── docker-compose.yml # Servis tanımı
|
||
├── .env # Aktif env (git'e ekleme!)
|
||
└── .env.example # Örnek env
|
||
```
|
||
|
||
---
|
||
|
||
## Anthropic ↔ OpenAI Dönüşümü
|
||
|
||
Anthropic `/anthropic/*` istekleri otomatik olarak OpenAI formatına çevrilip `OPENAI_BACKEND`'e gönderilir, yanıt tekrar Anthropic formatına dönüştürülür:
|
||
|
||
**Request dönüşümü (Anthropic → OpenAI):**
|
||
```json
|
||
// Anthropic giriş
|
||
{ "model": "claude-3", "max_tokens": 100, "system": "You are helpful.", "messages": [{"role": "user", "content": "Hi"}] }
|
||
|
||
// Bifrost çıkış
|
||
{ "model": "claude-3", "max_tokens": 100, "messages": [{"role": "system", "content": "You are helpful."}, {"role": "user", "content": "Hi"}] }
|
||
```
|
||
|
||
**Response dönüşümü (OpenAI → Anthropic):**
|
||
```json
|
||
// Bifrost giriş
|
||
{ "choices": [{"message": {"role": "assistant", "content": "Hello!"}, "finish_reason": "stop"}] }
|
||
|
||
// Anthropic çıkış
|
||
{ "type": "message", "role": "assistant", "content": [{"type": "text", "text": "Hello!"}], "stop_reason": "stop" }
|
||
```
|
||
|
||
---
|
||
|
||
## Lisans
|
||
|
||
MIT
|