Loading
Loading
In this lesson you'll deploy a real AI API on the free ARM VM.
User โ Nginx (HTTPS) โ FastAPI (8080) โ Claude API
import json
import os
from datetime import datetime
from dataclasses import dataclass, field
from typing import Dict, List, Optional
# โโโ ู
ุญุงูุงุฉ FastAPI AI Server โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
@dataclass
class ServerConfig:
host: str = "0.0.0.0"
port: int = 8080
workers: int = 4
claude_model: str = "claude-3-haiku-20240307"
max_tokens: int = 1024
rate_limit: int = 100 # ุทูุจุงุช/ุฏูููุฉ
PROJECT_FILES = {
"requirements.txt": """fastapi==0.111.0
uvicorn[standard]==0.29.0
anthropic==0.28.0
python-dotenv==1.0.1
pydantic==2.7.0
slowapi==0.1.9
""",
"app/main.py": """import os
from fastapi import FastAPI, HTTPException, Request
from pydantic import BaseModel
from anthropic import Anthropic
from dotenv import load_dotenv
load_dotenv()
app = FastAPI(title="AI API on Oracle Cloud ARM")
client = Anthropic(api_key=os.getenv("ANTHROPIC_API_KEY"))
class ChatRequest(BaseModel):
message: str
max_tokens: int = 1024
@app.get("/health")
def health(): return {"status": "ok", "model": "claude-3-haiku"}
@app.post("/chat")
def chat(req: ChatRequest):
resp = client.messages.create(
model="claude-3-haiku-20240307",
max_tokens=req.max_tokens,
messages=[{"role": "user", "content": req.message}],
)
return {"reply": resp.content[0].text, "tokens": resp.usage.input_tokens}
""",
"nginx.conf": """server {
listen 80;
server_name _;
location / {
proxy_pass http://127.0.0.1:8080;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_read_timeout 30s;
}
}
""",
"ai-api.service": """[Unit]
Description=AI FastAPI Service
After=network.target
[Service]
User=ubuntu
WorkingDirectory=/opt/ai-api
ExecStart=/opt/ai-env/bin/uvicorn app.main:app --host 0.0.0.0 --port 8080 --workers 4
Restart=always
RestartSec=3
EnvironmentFile=/opt/ai-api/.env
[Install]
WantedBy=multi-user.target
""",
}
# โโโ ู
ุญุงูุงุฉ FastAPI Server โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
class ClaudeClient:
def ask(self, message: str) -> str:
return f"[Claude Haiku ุนูู Oracle ARM] ุฅุฌุงุจุชู: {message[:50]}..."
class AIServer:
def __init__(self, cfg: ServerConfig):
self.cfg = cfg
self.claude = ClaudeClient()
self._reqs = 0
self._errors = 0
self._start = datetime.now()
def handle_request(self, path: str, body: dict = None) -> Dict:
self._reqs += 1
body = body or {}
if path == "/health":
uptime = (datetime.now() - self._start).seconds
return {"status": "ok", "uptime_s": uptime,
"model": self.cfg.claude_model,
"requests": self._reqs}
elif path == "/chat":
msg = body.get("message", "").strip()
if not msg:
self._errors += 1
return {"error": "message ู
ุทููุจ", "code": 400}
reply = self.claude.ask(msg)
return {"reply": reply, "model": self.cfg.claude_model}
elif path == "/stats":
err_rate = self._errors / max(self._reqs, 1)
err_str = f"{err_rate:.1%}"
return {"total_requests": self._reqs, "errors": self._errors,
"error_rate": err_str, "workers": self.cfg.workers}
self._errors += 1
return {"error": "Not Found", "code": 404}
# โโโ ุนุฑุถ ุงูู
ุดุฑูุน โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
print("๐ด ู
ุดุฑูุน: AI API ุนูู Oracle Cloud ARM")
print("=" * 55)
# ุนุฑุถ ู
ููุงุช ุงูู
ุดุฑูุน
print("\n๐ ู
ููุงุช ุงูู
ุดุฑูุน:")
for fname, content in PROJECT_FILES.items():
lines = content.strip().split("\n")
print(f" ๐ {fname} ({len(lines)} ุณุทุฑ)")
# ุชุดุบูู ุงูู
ุญุงูุงุฉ
print(f"\n\n๐ ุชุดุบูู FastAPI Server:")
cfg = ServerConfig(workers=4)
server = AIServer(cfg)
print(f" Host : {cfg.host}:{cfg.port}")
print(f" Workers : {cfg.workers}")
print(f" Model : {cfg.claude_model}")
# ุงุฎุชุจุงุฑ Endpoints
print(f"\n\n๐งช ุงุฎุชุจุงุฑ Endpoints:")
tests = [
("/health", {}),
("/chat", {"message": "ู
ุง ูู Oracle Cloud Always Freeุ"}),
("/chat", {"message": ""}), # ุฎุทุฃ
("/chat", {"message": "ููู ุฃูุดุฑ FastAPI ุนูู Oracle VMุ"}),
("/stats", {}),
]
for path, body in tests:
resp = server.handle_request(path, body)
code = resp.get("code", 200)
icon = "โ
" if code == 200 else "โ"
key = "reply" if "reply" in resp else ("status" if "status" in resp else list(resp.keys())[0])
val = str(resp.get(key, ""))[:60]
print(f" {icon} {path:<10} โ {key}: {val}")
# ุฎุทูุงุช ุงููุดุฑ
print(f"\n\n๐ ุฎุทูุงุช ุงููุดุฑ ุนูู Oracle ARM:")
steps = [
("ูุณุฎ ุงูู
ููุงุช", "scp -r app/ ubuntu@IP:/opt/ai-api/"),
("ุชุซุจูุช ู
ูุชุจุงุช", "pip install -r requirements.txt"),
("ุฅุนุฏุงุฏ .env", "echo 'ANTHROPIC_API_KEY=sk-...' > .env"),
("ุชูุนูู Service", "sudo systemctl enable ai-api && sudo systemctl start ai-api"),
("ุฅุนุฏุงุฏ Nginx", "sudo cp nginx.conf /etc/nginx/sites-enabled/ && sudo nginx -t -s reload"),
("ุงุฎุชุจุงุฑ", "curl http://YOUR_IP/health"),
]
for i, (desc, cmd) in enumerate(steps, 1):
print(f" {i}. {desc}")
print(f" $ {cmd}")
print()
print("โ
AI API ูุนู
ู ุนูู Oracle Cloud ู
ุฌุงูุงู ููุฃุจุฏ!")