Aller au contenu

Proxy compatible OpenAI

piighost-api sert un proxy compatible OpenAI sous /openai/v1. Pointez le base_url d'un client dessus, et le proxy dé-identifie chaque requête, la relaie au vrai fournisseur, puis restaure la réponse. Le fournisseur reçoit <<PERSON:1>>, jamais Jane Doe.

Pointer le client vers le proxy

Changez seulement le base_url. L'api_key reste la clé du fournisseur.

from openai import OpenAI

client = OpenAI(
    base_url="http://127.0.0.1:8000/openai/v1",
    api_key="sk-...",
)
response = client.chat.completions.create(
    model="gpt-5.6-terra",
    messages=[
        {
            "role": "user",
            "content": "Write a short greeting to Jane Doe, jane.doe@example.com.",
        }
    ],
)
print(response.choices[0].message.content)

Le fournisseur reçoit <<PERSON:1>> et <<EMAIL:1>>, et la réponse imprimée porte de nouveau Jane Doe. Les clés API_KEY_ du serveur ne s'appliquent pas à /openai/v1, parce que le proxy ne demande aucune clé de serveur. Il relaie l'en-tête Authorization au fournisseur tel quel.

Le même appel avec curl :

curl http://127.0.0.1:8000/openai/v1/chat/completions \
  -H "Authorization: Bearer sk-..." \
  -H "Content-Type: application/json" \
  -d '{"model": "gpt-5.6-terra", "messages": [{"role": "user", "content": "I am Jane Doe"}]}'

Choisir le fournisseur

Sans en-tête, le proxy relaie vers https://api.openai.com/v1. Si vous voulez un autre fournisseur compatible OpenAI pour tous les clients, posez PIIGHOST_OPENAI_UPSTREAM avant de démarrer le serveur :

export PIIGHOST_OPENAI_UPSTREAM="http://vllm.internal:8000/v1"

Si vous le voulez pour un seul client, nommez l'URL de base du fournisseur dans l'en-tête X-PIIGhost-Upstream :

client = OpenAI(
    base_url="http://127.0.0.1:8000/openai/v1",
    api_key="sk-...",
    default_headers={"X-PIIGhost-Upstream": "http://vllm.internal:8000/v1"},
)

Le proxy retire chaque en-tête X-PIIGhost-* avant de relayer, donc le fournisseur ne le voit jamais.

Garder une conversation d'une requête à l'autre

Chaque requête s'exécute dans une conversation neuve, oubliée dès que la réponse est restaurée. Un client de chat renvoie tout l'historique à chaque tour, donc la numérotation des placeholders reste cohérente au sein de chaque requête. Si vous voulez que la conversation survive à la requête, par exemple pour restaurer plus tard une réponse stockée via /v1/deanonymize, fixez-la avec X-PIIGhost-Thread-Id :

response = client.chat.completions.create(
    model="gpt-5.6-terra",
    messages=[{"role": "user", "content": "I am Jane Doe"}],
    extra_headers={"X-PIIGhost-Thread-Id": "user-42"},
)

Une conversation fixée reste dans la mémoire du serveur jusqu'à ce que DELETE /v1/threads/user-42 l'efface.

Streamer la réponse

stream=True fonctionne sans changement. Le proxy restaure chaque placeholder à l'arrivée des fragments, même quand le fournisseur coupe <<PERSON:1>> sur deux fragments.

stream = client.chat.completions.create(
    model="gpt-5.6-terra",
    messages=[{"role": "user", "content": "I am Jane Doe"}],
    stream=True,
)
for chunk in stream:
    if chunk.choices:
        print(chunk.choices[0].delta.content or "", end="")

Les routes que le proxy sert, et les champs qu'il dé-identifie sur chacune, sont listés dans Endpoints de l'API.

Voir aussi