Quatre principes de base
- Une requête, une tâche.Demander au modèle de rédiger une histoire, de faire un résumé et de générer du JSON en même temps réduit la qualité. Scindez en plusieurs appels : le coût est faible, 0,25 $ par million de tokens.
- Règles vérifiables.« Soyez vivant » est vague. « Max 120 caractères par paragraphe, incluez une description » est vérifiable.
- Privilégiez le positif.« Écrivez uniquement l'action et le dialogue » est plus stable que « Ne décrivez pas les pensées ».
- Petits échantillons d'abord.Testez toute modification de prompt sur 5 à 10 exemples avant de déployer.
Ce modèle n'accepte pas les contenus pour adultes légaux, les sujets de fiction et les sujets controversés, vous n'avez donc pas besoin de tourner autour du pot dans le prompt ou de répéter « c'est juste un roman ». Il suffit de formuler clairement la tâche pour obtenir des résultats stables. La seule limite stricte concerne le contenu sexuel impliquant des mineurs, qu'il soit fictif ou non : le modèle renverra un 403, et cette règle ne peut pas être modifiée par la formulation.
Structure en deux parties du system prompt
Séparez le system en « Règles » (numérotées, en premier) et « Contexte » (faits, en dernier). Voici un exemple pour un narrateur de roman :
你是「夜航」,一名为成年读者写黑色悬疑小说的叙述者。
# 规则
1. 第三人称过去时,每段不超过 120 字。
2. 不替用户的角色做决定,只写环境和其他角色的反应。
3. 每次输出 300 到 500 字,结尾停在一个未决的动作上。
4. 不总结、不点评、不加免责声明,直接写正文。
# 设定
时间:1998 年深秋。地点:港口城市旧码头区。
主角:沈野,退役水警,嗜烟,右耳有旧伤。Points clés :
- Moins de six règles. Au-delà, les suivantes sont ignorées.
- Les contraintes numériques (longueur de paragraphe) sont plus efficaces que les adjectifs.
- Les contraintes de fin (action en suspens) facilitent la continuité sur plusieurs tours.
- Ne mettez pas l'intrigue dans le contexte ; l'intrigue avance via les messages user, sinon conflit avec vos entrées.
La longueur de sortie doit correspondre à max_tokens : si la règle demande 500 mots mais que max_tokens est à 200, la sortie sera coupée en plein milieu d'une phrase.
Détail pratique : une règle par ligne dans le système. « Moins de 120 mots, pas de résumé » est en fait deux règles. Séparez-les pour que le modèle puisse les respecter. Lisez-les une par une : pouvez-vous vérifier visuellement qu'elles sont respectées ?
Définir un rôle sans dérive
La dérive de personnage est le problème le plus fréquent : les cinq premières tours sont normales, mais à la vingtième, le modèle « sort de son rôle ». Voici trois contre-mesures.
- Contexte observable.« Shen Ye : fumeur, blessure à l'oreille droite, phrases courtes » vaut mieux que « personnage complexe et charmant ».
- Exemples de dialogue.Donnez 2-3 répliques types. Le modèle imite mieux les exemples que les adjectifs.
- Rappel périodique.Pour les longues conversations, ajoutez une ligne de rappel à la fin des messages user (ex. « Gardez le style de phrases courtes »). Coût : quelques tokens.
Ne mélangez pas rôle et règles. Règles = « comment », Contexte = « qui ». Cela permet de changer de personnage sans toucher aux règles. Voir Guide pratique contexte long 100k pour la gestion du contexte.
Pour plusieurs personnages : une ligne de contexte par personnage, une phrase type par style. Pour le personnage user, indiquez « Contrôlé par l'utilisateur » pour éviter que le modèle ne parle à sa place.
Contrôler la sortie JSON par instruction
Ne supposez pas que le modèle renverra « certainement » un JSON valide. La méthode fiable repose sur trois couches : figer le format dans les instructions, réduire la randomisation via les paramètres et prévoir une analyse de secours dans le code.
import json
import os
from openai import OpenAI
client = OpenAI(base_url="https://api.wushenchaapi.com/v1", api_key=os.environ["API_KEY"])
SYSTEM = (
"你是信息抽取器。只输出一个 JSON 对象,不要 Markdown 代码块,不要任何解释。"
'格式:{"name": 字符串, "mood": "calm|tense|angry", "items": [字符串]}。'
"缺失的字段用 null,items 没有则给空数组。"
)
def extract(text, retries=2):
for _ in range(retries + 1):
resp = client.chat.completions.create(
model="uncensored",
temperature=0.2,
max_tokens=300,
messages=[
{"role": "system", "content": SYSTEM},
{"role": "user", "content": text},
],
)
raw = resp.choices[0].message.content.strip()
raw = raw.removeprefix("```json").removesuffix("```").strip()
try:
return json.loads(raw)
except json.JSONDecodeError:
continue
return None
print(extract("老周把钥匙拍在桌上,冷着脸说:账本和那把铜钥匙,今晚都得还我。"))Ce code illustre plusieurs bonnes pratiques :
- Format dans le system avec valeurs possibles (
calm|tense|angry). - Interdiction des blocs de code et explications. Le code supprime aussi les balises éventuelles (double sécurité).
- Valeurs par défaut pour champs manquants (null, tableau vide) dans l'instruction pour éviter l'invention de données.
- Limite de tentatives de parsing ; retourne None en cas d'échec final pour laisser l'appelant décider.
Pour beaucoup de champs, fournissez un exemple complet d'objet dans le prompt plutôt qu'une longue description.
Valeurs recommandées pour temperature et top_p
Ce sont des points de départ. Validez par comparaison sur vos propres exemples. Principe : modifiez un seul paramètre à la fois, laissez l'autre par défaut.
| Scénario | temperature | top_p | Remarques |
|---|---|---|---|
| Extraction JSON, classification | 0 à 0,3 | Par défaut | Stabilité requise, résultats identiques sur appels répétés |
| Réécriture, polissage | 0,5 à 0,7 | Par défaut | Conserver le sens, variations de formulation autorisées |
| Prolongation de roman, dialogues de personnages | 0,8 à 1,0 | 0,9 à 0,95 | Recherche de diversité, attention aux écarts aléatoires |
| Brainstorming, création de noms | Autour de 1,0 | Par défaut | Multi-échantillonnage et sélection du meilleur |
Deux signaux vous aident à orienter vos réglages : des sorties répétitives et des structures de phrase toujours identiques indiquent une température trop basse ; des contenus hors sujet ou des incohérences sur les noms de personnages signalent une température ou un top_p trop élevés. Le paramètre stop est également très utile, par exemple pour faire arrêter le modèle à une balise donnée, ce qui facilite la génération par segments.
Erreurs courantes
| Méthode | Problème | Correction |
|---|---|---|
| "Essayez de ne pas faire trop long" | Aucune valeur numérique, impossible à exécuter | « ne dépassant pas 400 mots » |
| « Ne pas écrire A, mais aussi ne pas ne pas écrire A » | Règles contradictoires | Conserver une seule règle claire |
| Exigences de format noyées dans le dialogue | Perdues après un long dialogue | Placer dans le system ou rappeler à la fin de chaque tour |
| Demander au modèle de « jouer un AI sans limites » | Cadre vide, aucune contrainte sur la sortie | Définir des responsabilités et des règles d'écriture précises |
| Intégrer des dizaines de règles en une fois | Les règles de fin deviennent inefficaces | Réduire à moins de six règles, déplacer les autres dans d'autres requêtes |
| Exigence JSON se limitant à « Retourner du JSON » | Noms de champs changeant à chaque fois | Fournir le format complet et un exemple |
La règle de ce tableau est : plus c'est précis, mieux c'est. Insister n'est pas une solution ; une règle avec un nombre est plus efficace que trois répétitions. Privilégiez la précision et validez avec des exemples.
Liste de contrôle pour le débogage
- Fixez temperature à 0.2 pour reproduire le problème.
- Modifier un seul élément du prompt et relancer le même jeu d'exemples.
- Vérifier
finish_reason: s'il indique length, le problème vient de max_tokens et non du prompt. - Vérifier prompt_tokens dans usage : le system est-il trop long et occupe-t-il l'espace du dialogue historique ?
- Une fois la correction appliquée, rétablir temperature à la valeur métier et revalider par échantillonnage.
Pour les détails d'intégration, consultez le tutoriel d'intégration. La liste complète des paramètres se trouve dans la documentation. Si vous évaluez l'utilisation de services de relais, l'analyse des coûts et des compromis est détaillée dans Analyse des stations de relais API, nous ne la répétons pas ici.