Skip to main content
Sprachmodelle sind gut darin, Texte zusammenzufassen, und schlecht darin, sich Fakten zu merken. In diesem Tutorial holen wir die Fakten aus dem Gedächtnis des Modells und stecken sie in den Prompt, sodass jeder Satz der Ausgabe auf eine Seite zurückverfolgt werden kann, die kurz zuvor abgerufen wurde. Wir bauen ein Kommandozeilen-Tool, das eine Frage mit einem kurzen, zitierten Briefing beantwortet:
Auf dem Weg dorthin werden wir:
  1. Mit /augment/search das Live-Web durchsuchen
  2. Entscheiden, welche dieser Ergebnisse es wert sind, gelesen zu werden
  3. Die ausgewählten Seiten mit /augment/scrape in Markdown umwandeln
  4. Ein Chat-Modell bitten, das Briefing zu schreiben und die Quellen per Nummer zu zitieren
  5. Die vier Stufen in einem Skript zusammenführen
Das Retrieval selbst zu übernehmen, anstatt es dem Modell zu überlassen, ist das, was das Ergebnis nachvollziehbar macht. Wir behalten die genaue Liste der Seiten, die in den Prompt geflossen sind, und können einer Leserin oder einem Leser zeigen, woher jede Aussage stammt. Wenn Sie das Retrieval lieber innerhalb einer einzigen Anfrage von Venice erledigen lassen möchten, setzen Sie stattdessen venice_parameters.enable_web_search in einer Chat Completion. Der Guide Websuche und Scraping vergleicht die beiden Ansätze.

Einrichtung

Sie benötigen Python 3.9 oder neuer, das Paket requests und einen Venice-API-Schlüssel. Siehe API-Schlüssel erzeugen, falls Sie noch keinen haben.
Erstellen Sie research.py und beginnen Sie mit den Imports und einem gemeinsamen Header-Block, den jeder Aufruf wiederverwendet:

1. Das Web durchsuchen

/augment/search nimmt eine Anfrage entgegen und liefert bis zu 20 gerankte Ergebnisse. Brave ist der Standardanbieter und wendet Zero Data Retention an. Google ist ebenfalls verfügbar und wird über Venice geproxyt, sodass die Anfrage nie mit Ihnen in Verbindung gebracht wird.
Jedes Ergebnis ist ein Objekt mit vier Feldern:
Zwei Dinge an dieser Antwort sollten Sie wissen, bevor Sie darauf aufbauen. Das Feld content kommt mit HTML darin an, weil der Anbieter Trefferbegriffe in <strong>-Tags einwickelt. Die HTML_TAG-Ersetzung oben entfernt sie, damit das Snippet als reiner Text zum Modell gelangt. Das Feld date ist häufig ein leerer String. Viele Seiten veröffentlichen kein maschinenlesbares Datum, behandeln Sie date daher als Hinweis, den Sie verwenden können, wenn er vorhanden ist, und nicht als Feld, nach dem Sie sortieren oder filtern können.
limit muss zwischen 1 und 20 liegen und query zwischen 1 und 400 Zeichen. Werte außerhalb dieser Bereiche liefern HTTP 400 mit einem Validierungs-Body. Sie werden nicht für Sie geklemmt.

2. Auswählen, welche Quellen gelesen werden sollen

Alle zehn Ergebnisse zu scrapen wäre langsam, teuer und weitgehend redundant. Suchmaschinen liefern mehrere Seiten von derselben Website, und Dokumentationsseiten insbesondere liefern dieselbe Seite in mehreren Sprachen, sodass derselbe Inhalt drei- oder viermal unter unterschiedlichen URLs auftauchen kann. Nur das am höchsten gerankte Ergebnis pro Domain zu behalten, entfernt den Großteil dieser Duplikate in wenigen Zeilen:
Angewendet auf die obigen zehn Ergebnisse werden sie auf vier verschiedene Websites eingegrenzt:
Dies ist die natürliche Stelle, um Ihre eigene Einschätzung einzubringen. Sie könnten Domains, denen Sie vertrauen, auf eine Allowlist setzen, Ergebnisse verwerfen, deren Snippet die Schlüsselbegriffe nie erwähnt, oder Ergebnisse mit einem aktuellen date bevorzugen. Jeder Filter, den Sie hier anwenden, ist eine Entscheidung, bei der das Modell keine Chance mehr hat, sie falsch zu treffen.

3. Die ausgewählten Seiten scrapen

/augment/scrape ruft eine öffentliche URL ab und liefert sie als Markdown zurück. Zuerst fragt es die Seite nach einer nativen Markdown-Darstellung und weicht auf browserbasierte Extraktion aus, wenn keine vorhanden ist. Einige Seiten werden fehlschlagen, und ein Recherche-Tool sollte das als Routine und nicht als fatal behandeln:
Beide Prüfungen sind ihren Platz wert. Die Statusprüfung fängt Seiten ab, die automatisierten Zugriff ablehnen, und die Längenprüfung fängt Seiten ab, die 200 liefern, aber ein Cookie-Banner oder eine leere Hülle statt eines Artikels zurückgeben.
Fehlgeschlagene Scrapes liefern einen einfachen {"error": "..."}-Body mit einer lesbaren Meldung, zum Beispiel X (formerly Twitter) blocks automated access to their content. X und Reddit sind grundsätzlich blockiert. Um Beiträge von X in eine Antwort einzubinden, verwenden Sie stattdessen venice_parameters.enable_x_search in einer Chat Completion.
Die Requests hängen nicht voneinander ab, führen Sie sie also parallel aus. Wenn wir schon dabei sind, begrenzen wir auch, wie viel von jeder Seite wir behalten:
Die dritte Seite kam mit genau 12000 Zeichen zurück, was bedeutet, dass sie länger als das Budget war und abgeschnitten wurde.
Das char_budget ist keine Nettigkeit. Suchergebnisse enthalten regelmäßig Aggregatseiten wie Sitemaps, Changelogs und llms-full.txt-Dateien, und eine einzige davon kann fast eine Million Zeichen zurückliefern. Ohne Obergrenze bestimmt ein einzelnes Pech-Ergebnis, was die gesamte Anfrage kostet.

4. Das Briefing schreiben

Jetzt übergeben wir dem Modell die gesammelten, nummerierten Seiten und bitten um Zitate, die auf diese Nummern verweisen. Die Nummerierung im Prompt ist das, was es uns erlaubt, ein [2] in der Ausgabe später wieder in eine URL umzuwandeln.
Eine niedrige temperature hält die Formulierung nah am Quelltext. enable_web_search auf off zu setzen entspricht dem Standard, aber es explizit auszusprechen garantiert, dass das Modell nicht stillschweigend eine Quelle einführen kann, die in unserer Referenzliste fehlt.

5. Alles zusammenfügen

Das letzte Stück führt die Stufen der Reihe nach aus und hängt die Referenzliste an, die die Zitatnummern auflöst:
Fortschrittsmeldungen gehen an stderr, sodass Sie das Briefing allein in eine Datei umleiten können:
Hier ist der Anfang des erzeugten Briefings, in gekürzter Form:
Beachten Sie, dass Quelle 3 in diesem Auszug nie zitiert wird. Genau dieses Verhalten wollen wir. Das Modell hat die Quellen genutzt, die relevant waren, und den Rest in Ruhe gelassen, und weil die Zitate nummeriert sind, können Sie das auf einen Blick erkennen.

Die Pipeline optimieren

Der größte Teil der Laufzeit entfällt auf die abschließende Chat Completion, da sich vier gescrapte Seiten auf zehntausende Tokens summieren. Das sind die Stellschrauben, an denen es sich zuerst zu drehen lohnt:

Nächste Schritte

Die Pipeline, die Sie jetzt haben, ist eine Grundlage und kein fertiges Produkt. Ein paar Richtungen, die es zu erkunden lohnt:
  • Gescrapte Markdown-Inhalte pro URL cachen, damit wiederholte Fragen nicht dieselben Seiten erneut abrufen.
  • Das Markdown mit Embeddings als Vektoren speichern und Passagen statt ganzer Seiten abrufen.
  • Das Modell mehrere Anfragen planen lassen, bevor gesucht wird, wie es die Demo Private Research Agent tut.
  • Das Briefing laut vorlesen lassen, indem Sie es in Artikel mit Text-to-Speech vertonen einspeisen.

Websuche und Scraping

Referenz für die Search- und Scrape-Endpunkte.

Artikel mit Text-to-Speech vertonen

Machen Sie aus dem gerade erzeugten Text Audio.

Embeddings

Gescrapte Markdown-Inhalte indexieren, statt sie erneut abzurufen.

Private Research Agent

Ein größerer Agent, der seine eigenen Suchen plant.