API opérationnelle · ai.bakeli.tech

L'IA pour toute
l'infrastructure
Bakeli

Un seul endpoint pour tous vos projets. Modèles LLM locaux, zéro coût d'API, données sur vos serveurs.

Premier appel API
import requests resp = requests.post( "https://ai.bakeli.tech/v1/chat", headers={"Authorization": "Bearer <API_KEY>"}, json={ "model": "llama3.2", "messages": [{"role": "user", "content": "Bonjour !"}] } ) print(resp.json()["message"]["content"])
Tout ce dont vos apps ont besoin

Une API simple, puissante, et compatible avec vos stacks existants.

💬
Chat conversationnel
Historique multi-tours, contexte système, réponses structurées.
📄
Analyse de fichiers
PDF, images, documents texte — extraction et raisonnement.
Streaming temps réel
Réponses en streaming ndjson pour une UX fluide.
🤖
Multi-modèles
Llama 3, Mistral, Gemma, LLaVA. Changez de modèle par requête.
🔐
Auth par clé API
Header Bearer standard. Une clé par application.
🏠
100% local
Zéro appel externe. Données sur vos serveurs. Zéro coût.
4 endpoints, tout compris

Interface REST simple, même pattern que Gemini et OpenAI.

POST /v1/chat Chat texte avec historique et streaming
POST /v1/chat/file Analyse de fichiers — PDF, images, texte
GET /v1/models Liste des modèles disponibles
GET /v1/health Healthcheck sans authentification
Guides par framework

Exemples complets et modules réutilisables pour chaque stack.

🐍
Django / Python
Guide complet
Module client réutilisable, views, historique.
🔴
Laravel / PHP
Guide complet
Service injectable, facade, upload de fichiers.
⚛️
React / Next.js
Guide complet
API Route sécurisée, hook React, streaming.
/ Documentation v1.0
Opérationnel
Bakeli SI · AI RedTeam

Vue d'ensemble

API IA centralisée pour toute l'infrastructure Bakeli SI. Un seul endpoint pour tous les projets — Django, Laravel, React, mobile.

Architecture

Flux
Tes apps → https://ai.bakeli.tech → NPM → ai-RedTeam:8000 → Ollama → LLM

Endpoints

MéthodeEndpointDescriptionAuth
POST/v1/chatChat texte + streaming
POST/v1/chat/fileChat + fichier joint
GET/v1/modelsListe des modèles
GET/v1/healthHealthcheck
Démarrage

Démarrage rapide

Ton premier appel en moins de 2 minutes.

1
Obtenir la clé API
Demande la API_KEY à l'équipe infra.
2
Premier appel avec cURL
bash
curl -X POST https://ai.bakeli.tech/v1/chat \
  -H "Authorization: Bearer <ta-cle-api>" \
  -H "Content-Type: application/json" \
  -d '{"model":"llama3.2","messages":[{"role":"user","content":"Bonjour !"}]}'

Réponse attendue

json — 200 OK
{ "model": "llama3.2", "message": { "role": "assistant", "content": "Bonjour !" }, "done": true }
💡Envoie tout l'historique dans messages pour maintenir le contexte entre les tours.
Sécurité

Authentification

Tous les endpoints sauf /v1/health requièrent une clé API.

Header requis

HTTP
Authorization: Bearer <API_KEY>
json — 401
{ "error": "Unauthorized" }
⚠️Ne jamais exposer la clé API côté browser. Appels uniquement depuis le backend.

Stocker la clé

.env
BAKELI_AI_URL=https://ai.bakeli.tech
BAKELI_AI_KEY=ta-cle-api-secrete
API Reference

POST /v1/chat

Chat texte avec historique. Supporte le streaming ndjson.

POST/v1/chat
ChampTypeDéfautDescription
modelstringllama3.2Modèle à utiliser
messagesarrayrequisTableau {role, content}
streambooleanfalseActive le streaming

Exemples

bash
curl -X POST https://ai.bakeli.tech/v1/chat \
  -H "Authorization: Bearer <API_KEY>" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "llama3.2",
    "messages": [
      {"role": "system", "content": "Tu es un assistant Bakeli SI."},
      {"role": "user",   "content": "Explique Docker en 3 lignes."}
    ]
  }'
python
import requests

resp = requests.post(
    "https://ai.bakeli.tech/v1/chat",
    headers={"Authorization": "Bearer <API_KEY>"},
    json={
        "model": "llama3.2",
        "messages": [
            {"role": "system", "content": "Tu es un assistant Bakeli SI."},
            {"role": "user",   "content": "Explique Docker en 3 lignes."},
        ],
    },
    timeout=120,
)
print(resp.json()["message"]["content"])
php
$ch = curl_init('https://ai.bakeli.tech/v1/chat');
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_POST           => true,
    CURLOPT_HTTPHEADER     => [
        'Authorization: Bearer <API_KEY>',
        'Content-Type: application/json',
    ],
    CURLOPT_POSTFIELDS => json_encode([
        'model'    => 'llama3.2',
        'messages' => [
            ['role' => 'system', 'content' => 'Tu es un assistant Bakeli SI.'],
            ['role' => 'user',   'content' => 'Explique Docker en 3 lignes.'],
        ],
    ]),
    CURLOPT_TIMEOUT => 120,
]);
$r = json_decode(curl_exec($ch), true);
echo $r['message']['content'];
javascript
const res = await fetch("https://ai.bakeli.tech/v1/chat", {
  method: "POST",
  headers: {
    "Content-Type":  "application/json",
    "Authorization": "Bearer <API_KEY>",
  },
  body: JSON.stringify({
    model: "llama3.2",
    messages: [
      { role: "system", content: "Tu es un assistant Bakeli SI." },
      { role: "user",   content: "Explique Docker en 3 lignes." },
    ],
  }),
});
const data = await res.json();
console.log(data.message.content);

Réponse

json — 200
{
  "model":   "llama3.2",
  "message": { "role": "assistant", "content": "Docker est..." },
  "done": true
}
API Reference

POST /v1/chat/file

Envoie un fichier (PDF, image, texte) avec un prompt. Le modèle analyse le contenu.

POST/v1/chat/file

Content-Type : multipart/form-data

ChampTypeDescription
promptstringQuestion sur le fichier
modelstringModèle (défaut: llama3.2)
filefileFichier à analyser
Type MIMETraitementModèle recommandé
image/*Base64 → champ imagesllava, gemma3:4b
application/pdfTexte extrait → contexte (8k)llama3.2, mistral
text/*Injection directeTous

Exemples

bash
curl -X POST https://ai.bakeli.tech/v1/chat/file \
  -H "Authorization: Bearer <API_KEY>" \
  -F "prompt=Résume en 5 points clés" \
  -F "model=llama3.2" \
  -F "file=@/chemin/document.pdf"
python
with open("document.pdf", "rb") as f:
    resp = requests.post(
        "https://ai.bakeli.tech/v1/chat/file",
        headers={"Authorization": "Bearer <API_KEY>"},
        data={"prompt": "Résume en 5 points", "model": "llama3.2"},
        files={"file": f},
        timeout=180,
    )
php
$ch = curl_init('https://ai.bakeli.tech/v1/chat/file');
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_POST           => true,
    CURLOPT_HTTPHEADER     => ['Authorization: Bearer <API_KEY>'],
    CURLOPT_POSTFIELDS     => [
        'prompt' => 'Résume en 5 points',
        'model'  => 'llama3.2',
        'file'   => new CURLFile('/chemin/document.pdf'),
    ],
    CURLOPT_TIMEOUT => 180,
]);
$r = json_decode(curl_exec($ch), true);
API Reference

GET /v1/models

Liste les modèles installés sur l'instance Ollama.

bash
curl https://ai.bakeli.tech/v1/models -H "Authorization: Bearer <API_KEY>"

Réponse

json — 200
{ "models": [{ "name": "llama3.2:latest", "size": 2019383552 }, ...] }
API Reference

GET /v1/health

Healthcheck sans authentification. Utilisé par NPM et les outils de monitoring.

bash
curl https://ai.bakeli.tech/v1/health
json — OK
{ "RedTeam": "ok", "ollama": "ok" }
json — Ollama arrêté
{ "RedTeam": "ok", "ollama": "unreachable" }
Intégration

Django / Python

Module client réutilisable à copier dans chaque app Django de l'infrastructure Bakeli.

1 — Variables d'environnement

.env
BAKELI_AI_URL=https://ai.bakeli.tech
BAKELI_AI_KEY=ta-cle-api
settings.py
BAKELI_AI_URL = env("BAKELI_AI_URL", default="https://ai.bakeli.tech")
BAKELI_AI_KEY = env("BAKELI_AI_KEY")

2 — Module client

python — utils/ai_client.py
import requests
from django.conf import settings

def ask(messages: list, model: str = "llama3.2") -> str:
    """Envoie une conversation, retourne le texte de réponse."""
    resp = requests.post(
        f"{settings.BAKELI_AI_URL}/v1/chat",
        headers={"Authorization": f"Bearer {settings.BAKELI_AI_KEY}"},
        json={"model": model, "messages": messages},
        timeout=120,
    )
    resp.raise_for_status()
    return resp.json()["message"]["content"]

def ask_with_file(prompt: str, filepath: str, model: str = "llama3.2") -> str:
    """Envoie un fichier avec un prompt."""
    with open(filepath, "rb") as f:
        resp = requests.post(
            f"{settings.BAKELI_AI_URL}/v1/chat/file",
            headers={"Authorization": f"Bearer {settings.BAKELI_AI_KEY}"},
            data={"prompt": prompt, "model": model},
            files={"file": f},
            timeout=180,
        )
    return resp.json()["message"]["content"]

3 — Utilisation dans une view

python — views.py
from utils.ai_client import ask

def assistant(request):
    historique = request.session.get("chat_history", [])
    historique.append({"role": "user", "content": request.POST.get("message")})
    reponse = ask(historique)
    historique.append({"role": "assistant", "content": reponse})
    request.session["chat_history"] = historique
    return JsonResponse({"reponse": reponse})
Intégration

Laravel / PHP

Service injectable pour une intégration élégante dans l'architecture Laravel.

1 — Config

.env
BAKELI_AI_URL=https://ai.bakeli.tech
BAKELI_AI_KEY=ta-cle-api
config/ai.php
<?php
return [
    'url'     => env('BAKELI_AI_URL', 'https://ai.bakeli.tech'),
    'key'     => env('BAKELI_AI_KEY'),
    'model'   => env('BAKELI_AI_MODEL', 'llama3.2'),
    'timeout' => 120,
];

2 — AiService

php — app/Services/AiService.php
<?php
namespace App\Services;
use Illuminate\Support\Facades\Http;

class AiService
{
    private string $url, $key, $model;

    public function __construct() {
        $this->url   = config('ai.url');
        $this->key   = config('ai.key');
        $this->model = config('ai.model');
    }

    public function ask(array $messages, string $model = null): string
    {
        return Http::withToken($this->key)
            ->timeout(config('ai.timeout'))
            ->post($this->url . '/v1/chat', [
                'model'    => $model ?? $this->model,
                'messages' => $messages,
            ])->throw()->json('message.content');
    }

    public function askWithFile(string $prompt, string $path, string $model = null): string
    {
        return Http::withToken($this->key)
            ->timeout(180)
            ->attach('file', file_get_contents($path), basename($path))
            ->post($this->url . '/v1/chat/file', [
                'prompt' => $prompt,
                'model'  => $model ?? $this->model,
            ])->throw()->json('message.content');
    }
}

3 — Controller

php — AssistantController.php
class AssistantController extends Controller
{
    public function __construct(private AiService $ai) {}

    public function chat(Request $request)
    {
        $history   = session('chat_history', []);
        $history[] = ['role' => 'user', 'content' => $request->input('message')];
        $reply     = $this->ai->ask($history);
        $history[] = ['role' => 'assistant', 'content' => $reply];
        session(['chat_history' => $history]);
        return response()->json(['reply' => $reply]);
    }
}
Intégration

React / Next.js

API Route sécurisée côté serveur + hook React réutilisable côté client.

⚠️Ne jamais appeler ai.bakeli.tech directement depuis le browser. Utilise une API Route Next.js comme proxy.

1 — Variables d'environnement

.env.local
# Côté serveur uniquement (sans NEXT_PUBLIC_)
BAKELI_AI_URL=https://ai.bakeli.tech
BAKELI_AI_KEY=ta-cle-api

2 — API Route (proxy sécurisé)

typescript — app/api/ai/route.ts
import { NextRequest, NextResponse } from 'next/server';

export async function POST(req: NextRequest) {
  const body = await req.json();
  const resp = await fetch(`${process.env.BAKELI_AI_URL}/v1/chat`, {
    method: 'POST',
    headers: {
      'Content-Type':  'application/json',
      'Authorization': `Bearer ${process.env.BAKELI_AI_KEY}`,
    },
    body: JSON.stringify(body),
  });
  return NextResponse.json(await resp.json());
}

3 — Hook React

typescript — hooks/useAI.ts
import { useState, useCallback } from 'react';

type Message = { role: 'user' | 'assistant'; content: string };

export function useAI(model = 'llama3.2') {
  const [loading, setLoading]   = useState(false);
  const [messages, setMessages] = useState<Message[]>([]);

  const ask = useCallback(async (userMessage: string) => {
    const updated = [...messages, { role: 'user' as const, content: userMessage }];
    setMessages(updated);
    setLoading(true);
    try {
      const res  = await fetch('/api/ai', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ model, messages: updated }),
      });
      const data  = await res.json();
      const reply = data.message.content;
      setMessages(prev => [...prev, { role: 'assistant', content: reply }]);
      return reply;
    } finally { setLoading(false); }
  }, [messages, model]);

  return { ask, loading, messages, reset: () => setMessages([]) };
}

4 — Composant Chat

tsx — ChatWidget.tsx
import { useState } from 'react';
import { useAI } from '@/hooks/useAI';

export default function ChatWidget() {
  const { ask, loading, messages } = useAI();
  const [input, setInput] = useState('');

  return (
    <div>
      {messages.map((m, i) => <div key={i}>{m.content}</div>)}
      <input value={input} onChange={e => setInput(e.target.value)} />
      <button onClick={() => { ask(input); setInput(''); }} disabled={loading}>
        {loading ? '...' : 'Envoyer'}
      </button>
    </div>
  );
}
Intégration

Migration depuis Gemini

Remplace l'API Gemini par l'IA locale Bakeli. Le format messages est identique.

Même résultat. Zéro coût. Données hébergées sur le serveur Bakeli.

Avant → Après

python — AVANT (Gemini)
import google.generativeai as genai
genai.configure(api_key="AIza...")
model = genai.GenerativeModel("gemini-pro")
text = model.generate_content("Explique Docker").text
python — APRÈS (Bakeli AI)
from utils.ai_client import ask
text = ask([{"role": "user", "content": "Explique Docker"}])

Checklist

#Action
1Ajouter BAKELI_AI_URL et BAKELI_AI_KEY dans le .env
2Ajouter les variables dans settings.py / config/ai.php
3Copier le module client dans le projet
4Remplacer les appels genai.* par le module client
5Supprimer google-generativeai de requirements.txt
Référence

Modèles disponibles

Modèles LLM installés sur le serveur. GET /v1/models pour la liste en temps réel.

IdentifiantTailleRAM minUsage
llama3.22.0 GB4 GBUsage général, rapide ⚡
mistral4.1 GB8 GBRaisonnement, texte long
gemma3:4b3.3 GB6 GBMultilingue, proche Gemini
llava4.7 GB8 GBVision — analyse d'images 🖼️
phi32.3 GB4 GBCode, logique
💡Commence avec llama3.2 — il couvre 90% des besoins.
Référence

Codes d'erreur

Erreurs possibles, leurs causes et solutions.

CodeCauseSolution
400JSON mal forméVérifier le body
401Clé API invalideVérifier Authorization: Bearer ...
503Ollama arrêtédocker start ollama
502ai-RedTeam arrêtédocker-compose up -d ai-RedTeam
504TimeoutUtiliser llama3.2

Diagnostic

bash
curl https://ai.bakeli.tech/v1/health
docker logs -f ai-RedTeam
docker ps | grep -E "ollama|ai-RedTeam"