Membuat REST API Otomatis dengan AI

Membuat REST API Otomatis dengan AI

Membangun backend yang mampu memproses data non-terstruktur (seperti teks bebas, email, atau log) secara manual sering kali menjadi bottleneck. Solusi tradisional menggunakan regex atau NLP rules-based cepat menjadi rapuh saat variasi data meningkat.

Tutorial ini membahas arsitektur REST API yang menggunakan Large Language Models (LLM) sebagai engine logika inti. Kami akan menggunakan FastAPI untuk framework web, Pydantic untuk validasi data, dan Ollama untuk menjalankan model AI secara lokal (on-premise) demi keamanan data dan latensi rendah.

Arsitektur Sistem

Sistem ini terdiri dari tiga komponen utama:

  1. API Gateway (FastAPI): Menerima request HTTP, memvalidasi input, dan mengelola lifecycle request.
  2. AI Engine (Ollama): Menjalankan model LLM (misalnya llama3 atau mistral) untuk mengekstrak entitas atau mengklasifikasikan data.
  3. Data Layer (Pydantic): Memastikan output dari LLM (yang bersifat probabilistik) dikonversi menjadi struktur data yang valid dan konsisten sebelum dikirim ke client.

Prasyarat & Persiapan

Sebelum memulai, pastikan lingkungan pengembangan Anda memenuhi syarat berikut:

Langkah Demi Langkah

Step 1: Inisialisasi Proyek dan Struktur Direktori

Buat struktur proyek yang rapi untuk memisahkan logika API dan logika AI.

mkdir ai-api-tutorial
cd ai-api-tutorial
mkdir -p app/core app/api app/schemas
touch app/main.py app/core/ai_engine.py app/api/routes.py app/schemas/data.py

Step 2: Definisi Skema Data (Pydantic)

LLM sering kali mengembalikan JSON yang tidak konsisten. Kita harus mendefinisikan skema target yang ketat.

Buka app/schemas/data.py:

from pydantic import BaseModel, Field
from typing import Optional

class InvoiceInput(BaseModel):
    raw_text: str = Field(..., description="Teks mentah dari invoice atau email")

class InvoiceData(BaseModel):
    vendor_name: str
    total_amount: float
    currency: str
    due_date: Optional[str] = None
    confidence_score: float = Field(..., ge=0, le=1)

Step 3: Implementasi AI Engine

Kita akan membuat wrapper untuk berkomunikasi dengan Ollama. Gunakan prompt engineering yang ketat untuk memaksa output JSON.

Buka app/core/ai_engine.py:

import requests
import json
from typing import Dict, Any

class OllamaClient:
    def __init__(self, model_name: str = "mistral", base_url: str = "http://localhost:11434"):
        self.model_name = model_name
        self.base_url = base_url

    def extract_data(self, prompt: str, context: str) -> Dict[str, Any]:
        """
        Mengirim prompt ke Ollama dan memparse respons JSON.
        """
        url = f"{self.base_url}/api/generate"

        payload = {
            "model": self.model_name,
            "prompt": prompt,
            "stream": False,
            "options": {
                "temperature": 0.0, # Penting: Set 0 untuk deterministik
                "top_p": 0.9
            }
        }

        try:
            response = requests.post(url, json=payload, timeout=60)
            response.raise_for_status()

            result = response.json()
            raw_output = result.get("response", "")

            # Bersihkan output jika LLM menyertakan markdown code blocks
            if "```json" in raw_output:
                raw_output = raw_output.split("```json")[1].split("```")[0]
            elif "```" in raw_output:
                raw_output = raw_output.split("```")[1].split("```")[0]

            return json.loads(raw_output)
        except json.JSONDecodeError:
            raise ValueError("LLM gagal mengembalikan JSON valid")
        except requests.RequestException as e:
            raise ConnectionError(f"Gagal terhubung ke Ollama: {e}")

Step 4: Membuat Endpoint REST API

Sekarang hubungkan semuanya di FastAPI.

Buka app/main.py:

from fastapi import FastAPI, HTTPException
from app.schemas.data import InvoiceInput, InvoiceData
from app.core.ai_engine import OllamaClient
import json

app = FastAPI(title="AI Invoice Processor")
ai_engine = OllamaClient()

PROMPT_TEMPLATE = """
Kamu adalah asisten data yang ahli dalam ekstraksi informasi.
Analisis teks berikut dan ekstrak data invoice.
Kembalikan HANYA objek JSON valid dengan format:
{{
    "vendor_name": "string",
    "total_amount": float,
    "currency": "string",
    "due_date": "string atau null",
    "confidence_score": float
}}

Teks:
{context}
"""

@app.post("/api/v1/invoice/parse", response_model=InvoiceData)
async def parse_invoice(input_data: InvoiceInput):
    """
    Endpoint untuk memparse teks mentah menjadi data terstruktur.
    """
    try:
        # 1. Siapkan Prompt
        prompt = PROMPT_TEMPLATE.format(context=input_data.raw_text)

        # 2. Panggil AI Engine
        raw_result = ai_engine.extract_data(prompt, input_data.raw_text)

        # 3. Validasi dengan Pydantic
        # Pydantic akan melempar ValidationError jika struktur tidak cocok
        validated_data = InvoiceData(**raw_result)

        return validated_data

    except ValueError as e:
        raise HTTPException(status_code=500, detail=f"Error parsing AI: {str(e)}")
    except Exception as e:
        raise HTTPException(status_code=500, detail=f"Internal Server Error: {str(e)}")

Step 5: Menjalankan Server

Jalankan aplikasi menggunakan Uvicorn.

uvicorn app.main:app --reload --host 0.0.0.0 --port 8000

Step 6: Pengujian dengan cURL

Kirim request POST dengan contoh data invoice.

curl -X POST "http://localhost:8000/api/v1/invoice/parse" \
  -H "Content-Type: application/json" \
  -d '{
    "raw_text": "Dear Team, please find attached the invoice from Acme Corp. Total amount is $1,500.00 USD. Payment due by 2023-12-01. Regards, John."
  }'

Respons yang diharapkan:

{
  "vendor_name": "Acme Corp",
  "total_amount": 1500.0,
  "currency": "USD",
  "due_date": "2023-12-01",
  "confidence_score": 0.95
}

Tips Optimasi & Keamanan

  1. Temperature 0.0: Selalu set temperature ke 0 untuk tugas ekstraksi data. Nilai > 0 akan membuat output tidak konsisten (non-deterministik) yang berbahaya untuk pipeline data.
  2. Rate Limiting: LLM lokal memakan banyak resource. Implementasikan rate limiting di level API (misalnya menggunakan slowapi) untuk mencegah overload server.
  3. Validasi Skema Ketat: Jangan pernah percaya output LLM secara mentah. Selalu validasi tipe data (float vs string) menggunakan Pydantic. Jika LLM mengembalikan "1500" (string) padahal butuh float, Pydantic akan menangkap error tersebut.
  4. Caching: Jika input teks sering berulang, cache hasil ekstraksi menggunakan Redis atau in-memory cache untuk mengurangi beban komputasi AI.
  5. Fallback Logic: Jika confidence_score dari LLM di bawah ambang batas (misal 0.8), arahkan data ke antrean untuk review manual alih-alih menyimpannya otomatis.

Troubleshooting Error Umum

Error Penyebab Solusi
ConnectionError: Failed to connect Ollama tidak berjalan atau port salah. Pastikan ollama serve aktif dan port 11434 terbuka.
JSONDecodeError LLM menambahkan teks penjelasan di luar JSON. Perbaiki prompt: "Kembalikan HANYA JSON, tanpa markdown".
ValidationError Field wajib tidak ditemukan di output LLM. Tambahkan field Optional di Pydantic jika data bisa kosong, atau perbaiki prompt agar lebih spesifik.
Timeout Model terlalu besar untuk hardware. Gunakan model lebih kecil (misal llama3:8b atau phi3) atau optimalkan hardware.

Kesimpulan

Integrasi AI ke dalam REST API memungkinkan otomatisasi proses yang sebelumnya membutuhkan logika aturan yang kompleks. Dengan menggunakan FastAPI untuk struktur web dan Ollama untuk inferensi lokal, Anda mendapatkan sistem yang cepat, privat, dan mudah di-deploy.

Kunci keberhasilan terletak pada prompt engineering yang ketat dan validasi data yang robust. Jangan pernah melewatkan langkah validasi Pydantic, karena output AI bersifat probabilistik dan harus dinormalisasi sebelum masuk ke database produksi.

Untuk kebutuhan dokumentasi API yang lebih kompleks atau penulisan konten teknis terkait proyek ini, Anda dapat memanfaatkan tools seperti Notion AI untuk menyusun arsitektur sistem atau Jasper untuk menulis dokumentasi pengguna yang lebih ramah non-teknis.

🏷️ Topik Terkait: