Modul 02 · Lektion 2

Beispiele geben: Few-Shot-Prompts

Nutzerbeiträge in vier Kategorien einteilen – ohne Beispiele 18 richtig, mit 4 Beispielen 20 richtig. Wie man Beispiele auswählt, wie viele man nimmt und welche Nebenwirkungen sie haben.

  • Etwa 30 Minuten
  • Niveau: Einsteiger
  • Getestet: 2026-09-14 deepseek-flash

Code und Programmausgaben stehen genau so da, wie sie gelaufen sind – Kommentare und Ausgaben sind daher auf Chinesisch.

Manche Anforderungen lassen sich schwer in Worte fassen. Wo verläuft die Grenze zwischen „Fehler“ und „Nutzungsfrage“? Ein Nutzer fragt „Die Cookies sind nach der Weiterleitung weg, benutze ich das falsch?“; wohin gehört das? Du kannst eine lange Definition schreiben, aber oft geht es schneller, einfach ein paar Beispiele zu geben.

Dem Modell ein paar Beispiele „Eingabe → Ausgabe“ zu zeigen und es danach vorgehen zu lassen, heißt Few-Shot-Prompting. Ohne Beispiele direkt loszulegen, heißt Zero-Shot.

Experiment: Nutzerbeiträge klassifizieren

Die Maintainer von httpx bekommen jeden Tag allerlei Beiträge. Wir wollen, dass das Modell sie automatisch in vier Kategorien einteilt: Fehler, Funktionswunsch, Nutzungsfrage, Sonstiges. Ich habe 20 Beiträge vorbereitet und jeweils von Hand die richtige Kategorie markiert, zum Beispiel:

TESTS = [
    ("用 AsyncClient 并发 100 个请求,程序直接卡死,CPU 占满", "缺陷"),
    ("能不能加一个像 requests 那样的 Session 重试适配器?", "功能建议"),
    ("怎么给单个请求设置不同的超时时间?", "使用问题"),
    ("你们的文档网站打不开了", "其他"),
    # ……一共 20 条,每类 5 条,完整列表见 code/02-prompting/few_shot.py
]

Der Zero-Shot-Prompt erklärt nur die Klassifikationsregeln:

ZERO_SHOT = """把用户留言分成以下四类之一:缺陷、功能建议、使用问题、其他。
只输出类别名称。"""

Der Few-Shot-Prompt fügt vier Beispiele hinzu, eines pro Kategorie, und keines davon ist im Testset:

FEW_SHOT = ZERO_SHOT + """

例子:
留言:调用 client.close() 之后再发请求没有报错,而是静默返回了旧的响应
类别:缺陷

留言:想要一个参数,能在请求失败时自动打印完整的请求和响应
类别:功能建议

留言:base_url 和 url 拼接的规则是什么?结尾的斜杠有没有影响
类别:使用问题

留言:这个项目和 aiohttp 比哪个更好
类别:其他"""

Jeder Beitrag geht im Format 留言:{text}\n类别: (Beitrag: {text}\nKategorie:) an das Modell, Temperatur 0, Denken aus, dann Vergleich mit der Handmarkierung:

def classify(system, text):
    response = client.chat.completions.create(
        model=MODEL,
        messages=[{"role": "system", "content": system}, {"role": "user", "content": f"留言:{text}\n类别:"}],
        temperature=0,
        extra_body={"thinking": {"type": "disabled"}},
    )
    return response.choices[0].message.content.strip()

Mein Ergebnis:

零样本:答对 18/20,格式不对 0 条 []
    怎么给单个请求设置不同的超时时间?  标注=使用问题  模型=功能建议
    你们的文档网站打不开了  标注=其他  模型=缺陷
少样本:答对 20/20,格式不对 0 条 []

Wo Zero-Shot falsch lag

Schauen wir die zwei Fehler von Zero-Shot an.

„怎么给单个请求设置不同的超时时间?“ (wie stelle ich für eine einzelne Anfrage ein anderes Timeout ein?) wurde als Funktionswunsch eingestuft. Vermutlich verstand das Modell es als „der Nutzer möchte eine Funktion, um für einzelne Anfragen ein Timeout zu setzen“. Das kann httpx aber längst; der Nutzer weiß nur nicht, wie man es schreibt.

„你们的文档网站打不开了“ (eure Dokumentationsseite lässt sich nicht öffnen) wurde als Fehler eingestuft. Wörtlich genommen ist eine Seite, die nicht aufgeht, tatsächlich ein Bug, aber unsere Kategorie „Fehler“ meint Probleme der Bibliothek httpx selbst; die Dokumentationsseite gehört zu „Sonstiges“.

Beide Fehler liegen nicht an einem dummen Modell, sondern daran, dass die Klassifikation Grauzonen hat, die meine Regeln nicht klar beschrieben. Mit Beispielen erkannte das Modell am Beispiel „nach welcher Regel werden base_url und url zusammengesetzt?“, dass „fragt, wie man etwas benutzt = Nutzungsfrage“, und an „ist dieses Projekt besser als aiohttp?“, dass „hat nichts mit der Bibliothek selbst zu tun = Sonstiges“. Die Beispiele haben die Regeln für mich klargestellt.

Du kannst natürlich auch ohne Beispiele die Regeln genauer schreiben: „Wer fragt, wie man etwas tut, stellt eine Nutzungsfrage, auch wenn es wie ein Funktionswunsch aussieht“, „nur Probleme mit dem Verhalten der Bibliothek httpx selbst sind Fehler“. Das wirkt auch und spart Tokens. In der Praxis nutzt man oft beides: Regeln für das Gerüst, Beispiele für die Details.

Wie man Beispiele auswählt

Jede Ausgabe abdecken. Für jede der vier Kategorien ein Beispiel. Gibt es nur Beispiele für „Fehler“ und „Nutzungsfrage“, gibt das Modell die anderen beiden Kategorien kaum noch aus.

Beispiele von der Grenze wählen. Die wertvollsten Beispiele sind nicht die typischsten, sondern die am leichtesten falsch eingestuften. „Nach close() kann man weiter Anfragen senden, ohne dass ein Fehler kommt“ ist ein gutes Beispiel: Es klingt nach einer Nutzungsfrage, ist aber tatsächlich ein Problem mit dem Verhalten der Bibliothek.

Vom Testset trennen. Beispiele dürfen nicht im Testset vorkommen, sonst verrät man dem Modell die Antworten und die Trefferquote ist geschönt. Die vier Beispiele in diesem Experiment habe ich eigens geschrieben.

Format wie bei der echten Eingabe. Die Beispiele haben das Format „留言:……类别:……“, und echte Anfragen nutzen dasselbe. Das Modell ahmt das Format der Beispiele genau nach; das Format der Beispiele ist also das Ausgabeformat, das du willst. In diesem Experiment gab es weder bei Zero-Shot noch bei Few-Shot Formatfehler, aber wenn du komplexere Ausgaben willst (etwa JSON), senkt ein korrekt formatiertes Beispiel Formatprobleme erheblich.

Wie viele

Meist reichen 3–5. Je mehr Beispiele, desto länger die Eingabe jeder Anfrage und desto höher die Kosten. Zum Glück sind Beispiele fest; in der system-Nachricht treffen sie den Cache.

Reicht die Wirkung noch nicht, überleg erst, ob die Beispiele schlecht gewählt sind, bevor du ihre Zahl erhöhst. Zehn ähnliche Beispiele sind schlechter als drei, die verschiedene Grenzfälle abdecken.

Nebenwirkungen von Beispielen

Beispiele wirken stark, und darum lenken sie das Modell auch leicht in die falsche Richtung.

Das Modell ahmt alles an den Beispielen nach. Sind die Antworten der Beispiele alle kurz, werden auch die Antworten des Modells kurz; sind die Beispiele alle auf Chinesisch, klassifiziert es auch englische Beiträge womöglich mit chinesischen Kategorienamen (was hier sogar erwünscht ist). Merkmale, die es nicht nachahmen soll, ahmt es trotzdem nach.

Das Modell kann den Inhalt der Beispiele übernehmen. Bei Generierungsaufgaben (etwa Produktbeschreibungen schreiben) können, wenn alle Beispiele über Kaffee sind, in einer Beschreibung von Tee Kaffeewörter auftauchen. Beispiele sollten daher vielfältig sein und sich inhaltlich unterscheiden.

Reihenfolge und Verhältnis wirken sich aus. Sind vier von fünf Beispielen „Fehler“, stuft das Modell eher als „Fehler“ ein. Halte die Zahl der Beispiele pro Kategorie möglichst ausgewogen.

Häufige Fragen

Beispiele in die system-Nachricht oder als mehrstufiges Gespräch? Beides geht. Oben stehen die Beispiele in der system-Nachricht. Die andere Variante macht aus jedem Beispiel ein Paar aus user- und assistant-Nachricht vor der eigentlichen Frage, als hätte das Modell schon ein paar Mal so geantwortet. Letzteres wirkt besonders gut beim Nachahmen des Formats, macht die Nachrichtenliste aber länger und schwerer zu pflegen. Ich fange meist mit der system-Nachricht an und wechsle, wenn das Format Probleme macht.

Was, wenn es sehr viele Kategorien gibt, etwa 30, und ein Beispiel pro Kategorie zu lang wird? Überleg zuerst, ob man die Kategorien in zwei Ebenen teilen kann: erst die Oberkategorie, dann die Unterkategorie. Oder man gibt nur den leicht verwechselbaren Kategorien Beispiele. Weiter geht man, indem man mit den Embeddings aus Modul 01, Lektion 5 aus einer großen Beispielsammlung die Beispiele heraussucht, die der aktuellen Eingabe am ähnlichsten sind, und nur diese in den Prompt legt. Das heißt dynamisches Few-Shot und funktioniert wie RAG in Modul 04.

Was dieses Experiment nicht zeigt

20 Testdaten sind zu wenig. Aus 18 gegen 20 wird mit anderen Daten vielleicht 19 gegen 20 oder sogar umgekehrt. Das Experiment ist ein konkretes Beispiel dafür, dass Few-Shot bei solchen Aufgaben hilft; es beweist nicht, dass Few-Shot die Trefferquote um 10 % erhöht. Um zwei Prompts verlässlich zu vergleichen, braucht man mehr Testdaten; das ist Thema von Lektion 5.

Übungen

  1. Reduzier die Beispiele im Few-Shot-Prompt auf zwei (nur „Fehler“ und „Nutzungsfrage“), lass es erneut laufen und schau, wie sich die Trefferquote bei „Sonstiges“ und „Funktionswunsch“ ändert.
  2. Nimm absichtlich vier Beispiele, die alle „Fehler“ sind, und schau, ob das Modell dann eher „Fehler“ wählt.
  3. Schreib selbst zehn weitere Beiträge, am besten solche, bei denen auch du nachdenken musst, um sie richtig einzuordnen, füg sie dem Testset hinzu und lass es erneut laufen. Ist der Abstand zwischen Zero-Shot und Few-Shot größer oder kleiner geworden?
  4. Ergänz statt Beispielen zwei Erläuterungen in den Zero-Shot-Regeln („wer fragt, wie man etwas benutzt, stellt eine Nutzungsfrage, auch wenn es nach einem Funktionswunsch aussieht“, „Dokumentation und Community gehören zu Sonstiges“) und schau, ob das ebenso gut wirkt wie Few-Shot.

Selbsttest

1. Warum dürfen die Beispiele eines Few-Shot-Prompts nicht im Testset vorkommen?

Die Beispiele verraten dem Modell die richtigen Antworten für diese Eingaben. Stehen dieselben Eingaben im Testset, muss das Modell sie nur abschreiben, die gemessene Trefferquote ist geschönt und spiegelt nicht die echte Leistung bei neuen Daten.

2. Du hast dem Modell fünf Beispiele gegeben, vier davon „Fehler“. Welches Problem kann entstehen?

Das Modell stuft eher mehr Beiträge als „Fehler“ ein, weil das Verhältnis der Beispiele nahelegt, dass „die meisten Beiträge Fehler sind“. Die Beispiele sollten die Kategorien möglichst ausgewogen abdecken, jede Ausgabe mindestens einmal.

3. Sollte man bei der Auswahl die typischsten Beispiele nehmen oder die am leichtesten falsch eingestuften?

Vorrangig die am leichtesten falsch eingestuften, die an der Grenze liegen. Typische Beispiele stuft das Modell ohnehin richtig ein; erst Beispiele von der Grenze helfen ihm, die Regeln in der Grauzone zu verstehen.

Fragen und Diskussion

Hängst du in dieser Lektion fest? Frag hier. Und wenn du die Frage von jemandem beantworten kannst, tu es gern.

Eine Frage bringt 3 Punkte, eine Antwort 6. Beiträge erscheinen nach der Prüfung.

Diskussion wird geladen…