File size: 5,611 Bytes
c63bc31
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
# L'API CORTEX AI

CORTEX AI expose une API **compatible OpenAI**. Tout client qui parle ce
protocole fonctionne en changeant seulement l'URL de base : le SDK Python
officiel, LangChain, LlamaIndex, ou un simple `curl`.

---

## Lancer le serveur

```bash
pip install -r requirements-ecosystem.txt

export PYTHONPATH=/chemin/vers/Cortex-ai:/chemin/vers/Cortex-ai/encoding
python -m cortex_ai.api.serve
```

Par défaut, le serveur démarre avec l'adaptateur simulé : aucune carte
graphique, aucun téléchargement. Pour charger le vrai modèle :

```bash
export CORTEX_ADAPTER=hf
```

---

## Configuration

Toutes les options passent par des variables d'environnement.

| Variable | Défaut | Effet |
|---|---|---|
| `CORTEX_MODEL_ID` | `Frankenstein-Labs/Cortex-ai` | Identifiant du modèle |
| `CORTEX_HOST` | `0.0.0.0` | Adresse d'écoute |
| `CORTEX_PORT` | `8000` | Port |
| `CORTEX_API_KEY` | vide | Si défini, authentification obligatoire |
| `CORTEX_THINKING_MODE` | `thinking` | `chat` ou `thinking` |
| `CORTEX_REASONING_EFFORT` | `high` | `low`, `high` ou `max` |
| `CORTEX_MAX_TOOL_ROUNDS` | `8` | Nombre maximal de tours d'outils |
| `CORTEX_TOOLS` | toutes | Liste séparée par des virgules |
| `CORTEX_ADAPTER` | `mock` | `mock` ou `hf` |

---

## Points d'accès

### `GET /health`

Vérifie que le serveur répond.

```bash
curl http://localhost:8000/health
```

```json
{
  "status": "ok",
  "model": "Frankenstein-Labs/Cortex-ai",
  "tools": ["calculate", "cortex_identity", "current_time", "text_stats"],
  "thinking_mode": "thinking"
}
```

### `GET /v1/models`

Liste les modèles disponibles, au format OpenAI.

```bash
curl http://localhost:8000/v1/models
```

### `POST /v1/chat/completions`

Le point d'accès principal.

```bash
curl http://localhost:8000/v1/chat/completions \
  -H "Content-Type: application/json" \
  -d '{
    "model": "Frankenstein-Labs/Cortex-ai",
    "messages": [{"role": "user", "content": "Combien font 12 * 8 ?"}]
  }'
```

Réponse :

```json
{
  "id": "chatcmpl-6bd0cefc9196421ba09b74d9",
  "object": "chat.completion",
  "created": 1789761504,
  "model": "Frankenstein-Labs/Cortex-ai",
  "choices": [
    {
      "index": 0,
      "message": {"role": "assistant", "content": "..."},
      "finish_reason": "stop"
    }
  ],
  "usage": {"prompt_tokens": 6, "completion_tokens": 9, "total_tokens": 15},
  "reasoning_content": "J'ai reçu le résultat de l'outil, je peux conclure.",
  "tool_calls": [
    {"name": "calculate", "arguments": {"expression": "12 * 8"}, "result": "96", "ok": true}
  ]
}
```

Deux champs s'ajoutent au format OpenAI :

| Champ | Contenu |
|---|---|
| `reasoning_content` | Le raisonnement du modèle, en mode `thinking` |
| `tool_calls` | Les outils réellement exécutés, avec leur résultat |

Ces champs sont additifs : un client OpenAI standard les ignore sans erreur.

---

## Le SDK OpenAI

Le SDK officiel fonctionne tel quel.

```python
from openai import OpenAI

client = OpenAI(base_url="http://localhost:8000/v1", api_key="peu-importe")

reponse = client.chat.completions.create(
    model="Frankenstein-Labs/Cortex-ai",
    messages=[{"role": "user", "content": "Combien font 12 * 8 ?"}],
)
print(reponse.choices[0].message.content)
```

Si vous avez défini `CORTEX_API_KEY`, passez la même valeur dans `api_key`.

---

## Le client Python inclus

Un client minimal, sans dépendance, est fourni.

```python
from cortex_ai.client import CortexClient

client = CortexClient("http://localhost:8000")

print(client.health()["status"])
print(client.models())

reponse = client.ask("Combien font 12 * 8 ?")
print(reponse.content)          # la réponse
print(reponse.reasoning)        # le raisonnement
print(reponse.tool_calls)       # les outils exécutés
print(reponse.usage)            # les compteurs de jetons
```

Pour conserver l'historique entre les appels :

```python
client.ask("Je m'appelle Abdoulaye.", keep_history=True)
client.ask("Comment je m'appelle ?", keep_history=True)
client.reset()  # effacer l'historique
```

---

## Authentification

Si `CORTEX_API_KEY` est défini, chaque requête doit porter l'en-tête :

```text
Authorization: Bearer <votre-cle>
```

Sans en-tête valide, le serveur répond `401 invalid API key`.

Sans `CORTEX_API_KEY`, aucune authentification n'est demandée. Ne l'exposez
jamais sur Internet dans cet état.

---

## Codes d'erreur

| Code | Cause |
|---|---|
| `400` | `messages` vide, ou `stream=true` demandé |
| `401` | Clé absente ou incorrecte |
| `422` | Corps de requête mal formé |

> **`stream=true` n'est pas encore pris en charge.** Le serveur refuse
> explicitement la demande plutôt que de renvoyer une réponse trompeuse.

---

## Ajouter un outil

```python
from cortex_ai.tools import tool, ToolRegistry
from cortex_ai.engine import CortexAgent
from cortex_ai.api import create_app
from cortex_ai.adapters import MockAdapter

@tool(description="Renvoie la longueur d'un texte.")
def longueur(texte: str) -> str:
    return str(len(texte))

agent = CortexAgent(MockAdapter(), ToolRegistry([longueur]))
app = create_app(agent.adapter)
```

Le schéma JSON est déduit des annotations de type. Le modèle reçoit
automatiquement la description de l'outil.

---

## Déploiement

En production :

```bash
export CORTEX_API_KEY="une-vraie-cle-longue"
export CORTEX_PORT=8000
export CORTEX_ADAPTER=hf

python -m uvicorn cortex_ai.api.server:create_app --factory --host 0.0.0.0 --port 8000
```

Placez le serveur derrière un reverse proxy avec TLS. Vérifiez le matériel
disponible : le checkpoint complet demande plusieurs accélérateurs.