Fazit
Das stimmt. Ich habe die Absicht falsch erfasst.
Genau genommen, ist es das hier.
1. Im ZIP befinden sich das ursprüngliche Markdown, das Schema, der Debugger und die Designdokumentation.
2. In deinem lokalen System ist bereits die konvertierte Version markdown → JSONL → DB vorhanden.
3. Was ich sehen kann, ist das „Markdown vor der Konvertierung und das DB‑Schema/Suchablauf“.
4. Daher muss der PoC das Markdown im ZIP in JSONL‑Chunks aufteilen und die Suchziele simulieren, die in deiner lokalen DB vorhanden sein könnten.
5. Was du möchtest, ist nicht das Codegerüst, sondern das Verfolgen des Ablaufs, wie jede Suchmethode Punkte erzeugt und warum sie erfolgreich bzw. fehlschlägt, wenn ein Chunk eingefügt wird.Und eine wichtige Änderung.
Der /api/retrieve des aktuellen Projekts ist nicht BM25.
Der aktuelle Code lautet:
chunkText
-> plainto_tsquery('simple', chunkText)
-> search_tsv @@ query
-> ts_rank_cd(...)Das ist. PostgreSQLs ts_rank_cd ist ein Full‑Text‑Ranking und kein reines BM25. Auch die PostgreSQL‑Dokumentation beschreibt ts_rank/ts_rank_cd als Ranking‑Funktionen, die eine Normalisierungsoption für die Dokumentlänge erhalten. plainto_tsquery tokenisiert den Eingabesatz, ignoriert Satzzeichen und erstellt aus Nicht‑Stop‑Wörtern eine Abfrage. (PostgreSQL)
Fazit
Die beste Lösung, die Ihre Bedingungen erfüllt, ist dies.
Eingabe:
raw chunkText unverändert
Retriever intern:
1. raw chunk unverändert BM25‑Kandidaten suchen
2. raw chunk unverändert Code‑Embedding‑Kandidaten suchen
3. Kandidaten vereinigen
4. mit Reranker neu ordnen
5. Qwen oder Validator prüft JSONL direkte BegründungDies ist die Version, bei der das Extrahieren von Godot‑API‑Signalen nicht zwingend erforderlich ist.
Das heißt, der von mir zuvor erwähnte „Godot API signal extractor“ darf nicht als zwingend erforderlich betrachtet werden. Wie du sagst, wirkt das nach Hardcoding. Es ist zwar nutzbar, aber wenn man es zum Kern des Grunddesigns macht, verschlechtert sich die Wartbarkeit.
Die endgültige Empfehlung ist:
Erster Kandidat: BM25
Zweiter Kandidat: code embedding
Endgültige Sortierung: reranker
Validierung: Qwen direct-evidence validatorProjektverständnis‑Verifizierung
Die tatsächliche Struktur, die im Zip‑Archiv zu sehen ist, sieht folgendermaßen aus.
JSONL‑Entwurf
Im Dokument sind die Ergebnisse wie folgt definiert.
work/godot_rag/jsonl/docs_chunks.jsonl
work/godot_rag/jsonl/api_mapping.jsonl
work/godot_rag/jsonl/label_prototypes.jsonl
work/godot_rag/jsonl/ingest_report.jsonlDas DB‑Schema ist nicht so aufgebaut, dass eine gesamte JSONL‑Zeile in payload jsonb eingefügt wird.
Die JSONL‑Felder werden als Tabellenspalten ausgeweitet.
docs_chunks:
chunk_id
doc_version
source_url
source_file
source_sha256
doc_type
symbol
section_path
heading
content
code_blocks
language_tags
godot_version_tags
api_symbols
token_count
metadata
embedding
search_tsv
api_mapping:
mapping_id
source_api
target_api
change_type
godot_from
godot_to
confidence
evidence_chunk_ids
match_terms
notes
negative_patterns
label_prototypes:
prototype_id
label
task_type
input_pattern
expected_finding
recommended_action
evidence_mapping_ids
evidence_chunk_ids
severity
validator_rules
embedding
search_tsvDas heißt, in deiner lokalen Datenbank wird es in etwa so aussehen.
{"chunk_id":"...","source_file":"outputs/godot_docs_full/pages/getting_started__first_2d_game__03.coding_the_player__161d377b.md","doc_type":"tutorial","heading":"Coding the player","content":"...","code_blocks":["func _process(delta): ..."],"api_symbols":["Input.is_action_pressed","Vector2.ZERO","AnimatedSprite2D","position.clamp"]}Vier Chunk Eingabe
Wir gehen davon aus, dass die Eingabe immer genau so ist.
func _process(delta):
var velocity = Vector2.ZERO
if Input.is_action_pressed(&"move_right"):
velocity.x += 1
if Input.is_action_pressed(&"move_left"):
velocity.x -= 1
if velocity.length() > 0:
velocity = velocity.normalized() * speed
$AnimatedSprite2D.play()
else:
$AnimatedSprite2D.stop()
position += velocity * delta
position = position.clamp(Vector2.ZERO, screen_size)Wenn man dieses Chunk mit einem Code‑Tokenizer betrachtet, sieht man die eindeutigen Token wie folgt.
_process
animatedsprite2d
clamp
delta
else
func
if
input
is_action_pressed
length
move_left
move_right
normalized
play
position
screen_size
speed
stop
var
vector2
velocity
x
zero
0
1Insgesamt 43 Token, davon 25 eindeutig.
Der wichtige Token hier ist dieser.
Starke Token:
animatedsprite2d
is_action_pressed
move_left
move_right
normalized
clamp
screen_size
vector2
zero
Schwache Token:
func
var
if
else
velocity
position
delta
x
0
1BM25 gibt starken Tokens eine hohe Punktzahl.
Denn je seltener ein Wort im gesamten Dokument vorkommt, desto größer wird der IDF.
Wie BM25 funktioniert und Ergebnisse liefert
BM25 berechnet grob „wie gut das Abfrage‑Wort im Dokument verankert ist“.
Formell gibt es drei Kernpunkte.
TF: Wie oft ein Wort in diesem Dokument vorkommt
IDF: Wie selten dieses Wort im gesamten Korpus ist
Length normalization: Korrektur, damit lange Dokumente nicht automatisch im Vorteil sindElasticsearch verwendet ebenfalls BM25 als Standard‑Relevanzalgorithmus und erklärt term frequency, inverse document frequency und field‑length normalization als Schlüsselelemente. (Elastic)
Die Formel sieht ungefähr so aus.
score(query, doc)
= Σ over query terms [
IDF(term)
*
TF_boost(term frequency in doc, doc length)
]Das heißt, wenn ein seltenes Wort wie animatedsprite2d mehrfach im Dokument vorkommt, steigt die Punktzahl erheblich.
Ergebnis der Simulation wie in der Realität
Originales Godot-Markdown im Zip:
outputs/godot_docs_full/pages/Ich habe dies in etwa 1800 Zeichen große Chunks wie JSONL docs_chunks aufgeteilt und die rohen Chunks unverändert als Abfrage in BM25 eingegeben.
Kandidat 1
Input.is_action_pressed("move_right")
Input.is_action_pressed("move_left")
velocity.length()
velocity.normalized() * speed
$AnimatedSprite2D.play()
$AnimatedSprite2D.stop()Warum es Platz 1 ist, diese Tokens haben direkt gepasst.
animatedsprite2d
is_action_pressed
move_left
move_right
normalized
play
stop
input
speed
length
velocity
vector2
zeroDie Top‑Beitragstoken, die die Punktzahl stark erhöht haben, sind folgende.
animatedsprite2d df=18 tf=7 contribution=11.975
is_action_pressed df=27 tf=2 contribution=8.609
move_left df=13 tf=1 contribution=7.479
velocity df=180 tf=18 contribution=7.467
move_right df=15 tf=1 contribution=7.299
normalized df=67 tf=2 contribution=7.069
stop df=133 tf=2 contribution=5.900
play df=144 tf=2 contribution=5.764
input df=323 tf=7 contribution=5.650
speed df=219 tf=3 contribution=5.637Hier ist df die Anzahl der Chunks, die das betreffende Wort enthalten, von insgesamt 4165 Chunks.
Das heißt:
animatedsprite2d erscheint nur in 18 von insgesamt 4165 Chunks
move_left erscheint nur in 13 Chunks
move_right erscheint nur in 15 Chunks
is_action_pressed erscheint nur in 27 ChunksDeshalb werden Dokumente, die diese Wörter enthalten, stark angezeigt.
Das ist der Prozess, wie BM25 den ersten Platz erreicht hat.
Zweiter Platz
AnimatedSprite2D Beschreibung
$AnimatedSprite2D.play()
get_node("AnimatedSprite2D").play()
position += velocity * delta
position = position.clamp(Vector2.ZERO, screen_size)Übereinstimmendes Token:
animatedsprite2d
clamp
screen_size
play
delta
_process
velocity
position
stop
vector2
zeroDieser Abschnitt belegt den zweiten Platz, weil zwar kein Eingabeverarbeitungs‑Teil vorhanden ist, aber clamp, screen_size und AnimatedSprite2D stark passen.
Insbesondere:
screen_size df=3
clamp df=32
animatedsprite2d df=18screen_size ist ein fast nie vorkommendes Wort, daher hat es selbst bei einmaligem Auftreten eine hohe Punktzahl.
Kandidat 3. Platz: Fehlkandidat
3D player movement
Input.is_action_pressed("move_right")
Input.is_action_pressed("move_left")
Vector3.ZERO
direction.normalized()
Chunk Inhalt:Übereinstimmendes Token:
is_action_pressed
move_left
move_right
normalized
speed
velocity
delta
input
x
var
func
zeroDas scheint relevant zu sein, ist aber nicht die genaue Antwort.
Warum es gepostet wurde:
Input.is_action_pressed
move_right
move_left
normalized
speedDies liegt daran, dass solche gemeinsamen Tokens des Bewegungscodes stark überlappen.
Aber dieses Dokument ist 3D. Ihr Chunk ist 2D, und AnimatedSprite2D, Vector2, position.clamp, screen_size sind zentral.
Das heißt, wenn man nur BM25 verwendet, entstehen solche Fehlalarme.
Der Grund, warum die aktuelle Methode fehlschlägt
Der Ansatz, der /api/retrieve nahe kommt, ist plainto_tsquery(raw_chunk).
Dieser Ansatz führt ungefähr zu einer solchen Abfrage.
func & process & delta & var & velocity & vector2 & zero
& input & is_action_pressed & move_right & move_left
& length & normalized & speed & animatedsprite2d
& play & stop & position & clamp & screen_sizeAuf diese Weise verlangt ein JSONL‑Chunk zu viele Tokens.
In meiner Simulation:
strict raw AND hits: 0Das heißt, wenn ein Chunk nicht gleichzeitig alle eindeutigen Token erfüllt, ist das Ergebnis 0.
Denn auch die offizielle Dokumentation ist so aufgeteilt.
chunk A:
Input.is_action_pressed
velocity.normalized
AnimatedSprite2D.play/stop
chunk B:
AnimatedSprite2D Beschreibung
position.clamp
screen_sizeBeide sind relevant, aber nicht alles ist in einer einzigen Zeile enthalten.
Deshalb ist es richtig, die aktuelle Vorgehensweise zu überarbeiten.
Methodenbezogene Alternativen
Alternative A. Aktuelle Methode: raw chunk + PostgreSQL plainto_tsquery
Ablauf:
raw chunkText
-> plainto_tsquery
-> search_tsv @@ query
-> ts_rank_cdJa Chunk Ergebnis:
Fehlerrate hoch
Selbst bei einer kleinen Änderung der Chunk‑Aufteilung gibt es 0 Fälle.Vorteile:
Implementierung ist bereits vorhanden
Nur mit PostgreSQL möglich
Einfache InfrastrukturNachteile:
Schwach bei langen Code‑Chunks
AND‑Bedingungen sind zu häufig
Viele Code‑Token‑Rauschen
Kein BM25
Semantische Suche nicht möglichBewertung:
EntsorgungAlternative B. Rohabschnitt + BM25 nur
Ablauf:
raw chunkText
-> tokenizer
-> BM25
-> top JSONL zurückgebenJa Chunk Ergebnis:
1. Platz: first_2d_game / coding_the_player
2. Platz: first_2d_game / coding_the_player / clamp Teil
3. Platz: first_3d_game / player_movement_codeWarum hat es funktioniert?
AnimatedSprite2D
move_right
move_left
is_action_pressed
screen_size
clampDiese Wörter sind in der gesamten Godot‑Dokumentation selten, sodass sie hohe Punkte erhalten haben.
Vorteile:
Prinzipien transparent
Einfach zu debuggen
Keine Modellkosten
Roh‑Chunk kann unverändert verwendet werden
Code/API ist stark bei genauen ZeichenkettenNachteile:
Schwach bei Synonymen/Beschreibungen
Wenn der API-Name nicht direkt erscheint, kann er nicht gefunden werden
Ähnlicher Code wird gemischt, wie bei 3D movement
Wird die Dokumentation anders ausgedrückt, wird es übersehenBewertung:
Muss unbedingt geschrieben werden
Aber allein ist es nicht ausreichendAlternative C. Roh-Chunk + Nur-Einbettung
Ablauf:
raw chunkText
-> embedding vector
-> docs_chunks/api_mapping/label_prototypes Embedding und Cosine‑Suche
-> top JSONL zurückgebenWarum das Modell verwendet wird:
Um Dokumente zu finden, deren Bedeutung nahe beieinander liegt, auch wenn die Zeichenketten nicht exakt übereinstimmen.Zum Beispiel enthält die Abfrage:
position.clamp(Vector2.ZERO, screen_size)Es gibt, und im Dokument:
prevent the player from leaving the screen
clamping a value means restricting it to a given rangeWenn es so erklärt wird, kann BM25 schwächer sein. Embedding erfasst solche semantischen Verbindungen.
Vorteile:
Auch bei unterschiedlicher Ausdrucksweise gefunden
Stark bei dokumentationsbeschreibendem Inhalt
Einfach, rohe Chunks unverändert einzufügen
Lange Chunks können ebenfalls verarbeitet werdenNachteile:
**Genaues API‑Urteil ist schwach**
3D/2D, Godot 3/Godot 4 – solche feinen Unterschiede können vermischt werden
Es ist schwer zu erklären, warum dieses Ergebnis entstanden ist
Im api_mapping besteht ein hohes Risiko für Fehlalarme (false positives)Ja, Chunk‑Vorhersage:
Erfolg:
first_2d_game / coding_the_player Hohe Wahrscheinlichkeit, dass es gefunden wird
Fehlschlag:
first_3d_game movement könnte ebenfalls mit hoher Wahrscheinlichkeit auftreten
weil die Bedeutung von “player movement” ähnlich istBewertung:
Einzelverwendung verboten
Zur Ergänzung von BM25‑Kandidaten verwendenAlternative D. raw chunk + BM25 + Einbettung parallel
Ablauf:
raw chunkText
-> BM25 top 50
-> embedding top 50
-> Zusammenführen
-> Punkte mischen
-> top JSONL zurückgebenDieser Ansatz ist ziemlich gut.
Der Chunk-Fluss:
Was BM25 erfasst:
Input.is_action_pressed
AnimatedSprite2D
position.clamp
screen_size
Was embedding erfasst:
player movement
2D movement tutorial
moving inside screen
animation based on movementVorteile:
Die Schwächen der Zeichenkettensuche und der semantischen Suche ergänzen sich gegenseitig
Auch ohne Qwen verbessert sich die erste Qualitätsstufe
Beibehaltung der raw‑chunk‑BedingungNachteile:
Score‑Kombinationstuning ist erforderlich
BM25‑Score und Vektor‑Score haben unterschiedliche Skalen
False Positives können nicht vollständig verhindert werdenBewertung:
Praktische MindestempfehlungAlternative E. Rohdaten‑Chunk + Qwen‑Abfrage‑JSON‑Erstellung + Suche
Um Hard‑Coding zu vermeiden, ist diese Vorgehensweise ebenfalls möglich.
Ablauf:
raw chunkText
-> Anfrage zur Erstellung von JSON für die Suche an Qwen
-> BM25/Vector-Suche mit dem erstellten JSON
-> Rückgabe von JSONL-KandidatenZum Beispiel Qwen‑Ausgabe:
{
"search_intent": "Godot 4 2D player movement tutorial",
"important_literals": [
"Input.is_action_pressed",
"Vector2.ZERO",
"AnimatedSprite2D",
"position.clamp",
"screen_size"
],
"likely_doc_topics": [
"first 2D game",
"coding the player",
"player movement",
"clamp position to screen",
"play and stop AnimatedSprite2D"
],
"migration_signals": []
}Dies ist eine Methode, bei der der Godot‑API‑Signal‑Extraktor nicht direkt hardcodiert wird. Stattdessen erstellt Qwen das Abfrageprofil.
Vorteile:
Wenig Hardcoding
Zusammenfassung der Absicht in komplexen Chunks möglich
Suchbegriffe können für Menschen lesbarer gemacht werden
Spezialisierte Godot‑Entscheidungen können Qwen überlassen werdenNachteile:
Langsam
Kosten entstehen
Kann Hinweise ohne Qwen erzeugen
Halluzination bereits ab der Vor‑Suchphase möglich
Eine direkte Evidenzprüfung des Rohchunks ist unbedingt erforderlichJa Chunk Erfolg:
Wenn Qwen AnimatedSprite2D / Input.is_action_pressed / position.clamp herausnimmt, ist es erfolgreich.Ja Chunk-Fehler:
Qwen erzeugt eine nicht vorhandene Absicht wie „Migration von Godot 3 zu 4“ und führt dadurch zu einer falschen api_mapping.Bewertung:
Gut für Suchqualitäts‑Experimente
Vorsichtig als primäre ProduktionssucheAlternative F. raw chunk + BM25 + embedding + reranker
Das ist am besten.
Ablauf:
- BM25 top 80
- embedding top 80
- Kandidaten‑Union
- Der Reranker vergleicht den Roh‑Chunk und jede JSONL‑Kandidatur direkt
- Gibt das beste JSONL zurück
- Der Qwen‑Validator prüft die direkte Begründungreranker liest die Abfrage und das Kandidatendokument gemeinsam und bewertet die Relevanz erneut. Das Voyage‑Dokument wird ebenfalls als ein Modell beschrieben, das den reranker verwendet, um die Kandidaten der ersten Suche wie embedding/BM25 nach einem Relevanz‑Score neu zu ordnen. rerank-2.5 ist ein qualitätsoptimierter reranker mit 32 K Kontext. (Voyage AI)
Die Aufgaben des rerankers im Chunk:
**Kandidat 1:**
first_2d_game / coding_the_player
Der raw chunk ist fast gleich dem direkten Codefluss.
=> **Sehr hoch**
**Kandidat 2:**
same page / clamp section
Es gibt eine Erklärung zu `position.clamp` und `AnimatedSprite2D`.
=> **Hoch**
**Kandidat 3:**
first_3d_game / player_movement
Input.is_action_pressed ist gleich, aber im Vector3/3D‑Kontext
AnimatedSprite2D keine
screen_size clamp fehlt
=> **Niedrig**Vorteile:
Beste Qualität
BM25‑Falschpositive stark reduziert
Embedding‑Falschpositive ebenfalls reduziert
Roh‑Chunk‑Bedingungen beibehalten
Hardcoding‑Abhängigkeit geringNachteile:
Kosten vorhanden
Latenz vorhanden
Wenn zu viele Kandidaten eingefügt werden, wird es langsam
Der Reranker ist ebenfalls kein Beweisprüfer, daher wird ein letzter Validator benötigtBewertung:
## Endgültige EmpfehlungWarum man das Modell verwendet und warum nicht
BM25 hat kein Modell
BM25 ist eine statistische Suche.
Dieses Wort ist in der Abfrage.
Dieses Wort ist auch im Dokument.
Dieses Wort ist im Korpus selten.
Dann wird die Punktzahl erhöht.Deshalb ist die Code‑Suche wie bei deinem Chunk stark.
AnimatedSprite2D
Input.is_action_pressed
Vector2.ZERO
position.clampIn solchen Fällen ist die Zeichenkette wichtiger als die Bedeutung.
Aber BM25 hat eine schwache Bedeutungsverknüpfung zu Ausdrücken wie „clamp darf nicht aus dem Bildschirm herausgehen“.
Warum ein Embedding‑Modell verwenden
Embedding wandelt Sätze in Vektoren um.
raw chunk
-> [0.12, -0.03, ...]
docs_chunk
-> [0.11, -0.02, ...]
cosine similarityDeshalb wird auch dann nach nahegelegenem Inhalt gesucht, wenn die Zeichenketten nicht exakt übereinstimmen.
Falls in diesem Projekt Einbettungen benötigt werden:
1. Wenn das Dokument beschreibend ist und Code und Wörter unterschiedlich sind
2. Wenn die API-Namen nicht kollidieren, aber das gleiche Konzept darstellen
3. Wenn das Tutorial‑Chunk in mehreren Ausdrücken verteilt ist
4. Wenn BM25 0 Treffer liefert und ein Fallback benötigt wirdFalls das Einbetten ausgeschlossen werden muss:
1. api_mapping source_api genaue Übereinstimmung
2. Godot3/Godot4 Versionsbestimmung
3. Entfernen von false positives, die nur target_api entsprechen
4. Bestätigung der MigrationsregelDas heißt:
embedding = recall Erweiterung
BM25/exact = direkter Beweis
reranker/Qwen validator = Kandidatenbereinigung und -validierungModelleigenschaften
voyage-code-3
Passt am besten zu diesem Projekt.
Grund:
query ist kein natürlicher Sprachfrage, sondern ein GDScript‑Code‑Chunk.
Die zu durchsuchenden JSONL‑Einträge enthalten ebenfalls Code‑Blöcke, API‑Namen und Dokumentationsbeschreibungen.Nach den offiziellen Dokumenten von Voyage voyage-code-3 ist ein für Code‑Retrieval optimiertes Modell, unterstützt 32 K Kontext, standardmäßig 1024 Dimensionen und 256/512/1024/2048 Dimensionen. In der Voyage‑Präsentation wird außerdem erklärt, dass es auf 32 Code‑Retrieval‑Datensätzen im Vergleich zu OpenAI text-embedding-3-large und CodeSage-large eine höhere durchschnittliche Leistung erzielt hat. (Voyage AI)
Eigenschaften:
Vorteile:
code query ist stark
Lange Chunk-Verarbeitung möglich
1024/2048 auswählbar
code -> docs für die Suche geeignet
Nachteile:
Externe API‑Abhängigkeit
Kosten entstehen
Kein Godot-spezifisches ModellEmpfohlene Verwendung:
voyage-code-3 1024 floatWenn man nur die Qualität betrachtet, ist 2048 auch möglich, aber 1024 + Reranker ist realistischer.
OpenAI text-embedding-3-large
Dies ist ein universelles hochwertiges Embedding.
Laut der offiziellen OpenAI‑Dokumentation hat text-embedding-3-large standardmäßig 3072 Dimensionen, und text-embedding-3-small hat standardmäßig 1536 Dimensionen. (OpenAI Entwickler)
Eigenschaften:
Vorteile:
Universelle semantische Suche ist stark
Stabil bei der Suche nach Dokumentenbeschreibungen
OpenAI-Ökosystem ist gut
Nachteile:
Nicht ausschließlich für Code‑Suche gedacht
3072 Dimensionen führen zu hohen Speicher‑/Indexierungskosten
Das „GDScript chunk → JSONL“ dieses Projekts ist weniger direkt als voyage‑code‑3Empfehlungsgrad:
Zweite PrioritätGemini Embedding
Google Gemini Embedding ist standardmäßig 3072‑dimensional, und mit output_dimensionality können Größen wie 768/1536/3072 gewählt werden. Google‑Dokumentation erklärt, dass bei Verwendung einer kleineren Dimension Speicherplatz und Rechenaufwand reduziert werden können, während der Qualitätsverlust gering bleibt. (Google AI for Developers)
Merkmale:
Vorteile:
Allgemeine/mehrsprachige semantische Suche ist stark
Gut für dokumentenbasierte beschreibende Suche
Dimensionsreduktion möglich
Nachteile:
Keine reine Code‑Retrieval‑Option
Fokussiert mehr auf Bedeutungsähnlichkeit als auf API‑Code‑Genauigkeit
Alleinige Verwendung bei genauer Beurteilung der Godot‑Migration ist riskantEmpfehlungsgrad:
Dokument‑QA‑zentriert wäre gut
Wenn der Fokus auf der Suche nach Code‑Chunks liegt, unter voyage-code-3Jina‑Einbettungen v4
Jina‑Einbettungen v4 ist ein Modell, das sich besonders für die Suche in komplexen Dokumenten, mehrsprachige, multimodale sowie visuell reiche Dokumente wie Tabellen, Diagramme und Bilder eignet. Nach den Angaben von Jina wird dabei besonders langer Input und die Retrieval‑Aufgabe für multimodale Dokumente hervorgehoben. (jina.ai)
Merkmale:
Vorteile:
Der Suchbereich des Dokuments ist breit.
multimodal/stark bei zusammengesetzten Dokumenten
code adapter ist ebenfalls vorhanden
Nachteile:
Dein Projekt ist derzeit markdown/code‑zentriert.
Bild-/Tabellenabruf ist nicht das Kernstück
könnte eine übermäßige Wahl seinEmpfehlungsgrad:
Im Moment ist die Priorität niedrig.Wenn Qwen für die Suche verwendet wird
Qwen ist, wie du sagst, derzeit im Bereich JSONL-Erstellung/Validierung.
Es kann auch für die Suche verwendet werden.
Es gibt zwei Arten der Verwendung.
1. Qwen query profile Generator
2. Qwen validator / rerankerQwen‑Abfrageprofil‑Generator
raw chunk
-> Qwen erstellt JSON für die Suche
-> BM25/Vector‑SucheVorteile:
Reduzierung von Hardcoding
Godot‑Kontextinferenz möglich
Komplexe Code‑Chunks zusammenfassen möglichNachteile:
hallucination möglich
Vor dem Suchschritt kann eine falsche Absichtseinspeisung möglich sein
Langsam
Kosten vorhandenQwen‑Validator
raw chunk
+ retrieved JSONL
-> Bewerten, ob dieses JSONL direkte Evidenz istDas ist stark. Im Projektbeobachtungsdokument ist bereits die Richtlinie festgelegt, dass nicht die breite Themenähnlichkeit, sondern das JSONL‑Feld und der Chunk‑String direkt übereinstimmen müssen.
Empfehlung:
Qwen ist sicherer, wenn es nach der Suche als direkter Evidenzvalidator verwendet wird, anstatt vor der Suche eine Abfrage zu erzeugen.Netzwerk‑Chunk‑basierter Erfolgs‑/Fehlablauf
Erfolgsablauf: BM25 + Einbettung + Reranker
Eingabe:
roher Chunk unverändertErster BM25 ist Rauschen:
first_2d_game / coding_the_player
Begründung:
Input.is_action_pressed
move_right
move_left
velocity.normalized
AnimatedSprite2D.play
AnimatedSprite2D.stopDer zweite BM25 ist Rauschen:
same page / clamp section
Begründung:
AnimatedSprite2D
position.clamp
Vector2.ZERO
screen_sizeEmbedding ist verbessert:
player movement
2D movement
animation based on movement
screen boundsReranker Zusammenfassung:
1. Platz:
first_2d_game / coding_the_player
2. Platz:
same page / clamp and AnimatedSprite2D explanation
Niedrigere:
first_3d_game / player_movement_codeEndgültiges JSONL:
{"table":"docs_chunks","payload":{"source_file":"outputs/godot_docs_full/pages/getting_started__first_2d_game__03.coding_the_player__161d377b.md","doc_type":"tutorial","heading":"Coding the player","content":"...Input.is_action_pressed...velocity.normalized...$AnimatedSprite2D.play()...$AnimatedSprite2D.stop()...","api_symbols":["Input.is_action_pressed","Vector2.ZERO","AnimatedSprite2D"]}}{"table":"docs_chunks","payload":{"source_file":"outputs/godot_docs_full/pages/getting_started__first_2d_game__03.coding_the_player__161d377b.md","doc_type":"tutorial","heading":"Coding the player","content":"...position += velocity * delta...position = position.clamp(Vector2.ZERO, screen_size)...","api_symbols":["Vector2.ZERO","position.clamp","AnimatedSprite2D"]}}Das ist ein Erfolg.
Fehlerablauf 1: aktueller raw tsquery
Eingabe:
roher Chunk unverändertInterne Abfrage:
func & process & delta & var & velocity & vector2 & zero
& input & is_action_pressed & move_right & move_left
& length & normalized & speed & animatedsprite2d
& play & stop & position & clamp & screen_sizeErgebnis:
0 Einträge möglichFehlergrund:
Fehlschlag, wenn nicht alle Wörter in einem JSONL‑Chunk enthalten sind.Das muss umgearbeitet werden.
Fehlablauf 2: BM25 only
Ergebnis:
1. Platz first_2d_game / coding_the_player
2. Platz same page / clamp section
3. Platz first_3d_game / player_movement_codeFehlergrund:
first_3d_game teilt ebenfalls Input.is_action_pressed, move_left, move_right, normalized.BM25 versteht nicht vollständig, ob es sich um „2D“ oder „3D“ handelt.
Es berechnet einfach nur die Wortpunkte.
Deshalb ist BM25 allein nicht ausreichend.
Fehlermeldungsablauf 3: Nur Einbettung
Erwartetes Ergebnis:
2D player movement
3D player movement
scripting player input
vector math
animation player docsFehlergrund:
Bedeutungsmäßig alles Spielerbewegung, also Näheembedding findet gut Dinge, die inhaltlich nah beieinander liegen, aber die API‑Genauigkeit ist schwach.
Fehlablauf 4: Qwen‑Abfrageprofil nur
Wenn Qwen so gut auswählt, ist es erfolgreich.
{"important_terms":["Input.is_action_pressed","AnimatedSprite2D","position.clamp","Vector2.ZERO"]}Aber wenn man es so auswählt, schlägt es fehl.
{"migration_intent":"Godot 3 to Godot 4 migration","important_terms":["AnimatedSprite","AnimatedSprite2D"]}Fehlergrund:
In raw chunk gibt es kein AnimatedSprite, nur AnimatedSprite2D.
Es ist gültiger Godot 4‑Code, jedoch kann das Migrations‑Mapping mitgebracht werden.Deshalb ist es gefährlich, Qwen nur als Query‑Generator vor der Suche zu verwenden. Nach der Suche ist der Validator sicherer.
Endgültige 3 Empfehlungen
Variante 1: geringste Komplexität
raw chunk
-> BM25
-> top JSONLVerwendung:
PoC 1. Phase
Schnelle visuelle Überprüfung der SuchqualitätVorteile:
Einfachheit
Schnell
Transparenz
Keine ModellkostenNachteile:
false positive vorhanden
Bedeutungssuche nicht möglich
Wenn die Dokumentdarstellung unterschiedlich ist, wird es übersehenIm Chunk:
Erfolg ist
Aber 3D movement ist gemischtOption 2: Ausgewogene Form
-> BM25 top 50
-> embedding top 50
-> union
-> weighted score
-> JSONL Rückgabe
-> Qwen Direct‑Evidence ÜberprüfungVerwendung:
Der realistisch beste Zwischenschritt im aktuellen ProjektVorteile:
BM25 und Embedding ergänzen
JSONL entfernen, die nicht mit Qwen zusammenhängen
Wenig HardcodingNachteile:
Punktzahl‑Anpassung erforderlich
Wenn kein Re‑Ranker vorhanden ist, ist das Ranking etwas instabilIm Chunk:
first_2d_game ist stabil und liegt an der Spitze
3D movement ist bei der Qwen‑Verifizierung gesunkenVariante 3: Qualität an erster Stelle
-> BM25 top 80
-> voyage-code-3 embedding top 80
-> union
-> rerank-2.5
-> Qwen direct-evidence validator
-> Endgültige JSONLVerwendung:
## Endgültige EmpfehlungVorteile:
Beste Qualität
Minimierung von Hardcoding
Beibehaltung der Roh‑Chunk‑Bedingungen
Der Reranker reduziert BM25/Embedding‑Fehlalarme
Der Qwen‑Validator entfernt JSONL ohne direkte BegründungNachteile:
Kosten
latency
Viele ImplementierungsstufenIm Chunk:
**Endgültige Annahme:**
docs_chunks / first_2d_game / coding_the_player
**Endgültige Ablehnung oder niedrigeres Ranking:**
first_3d_game / player_movement_code
unrelated api_mapping
migration label_prototypesEndgültiges Urteil
Wenn ich dieses Projekt jetzt umkremple, gehe ich so vor.
Der Input behält immer nur einen chunkText bei.
Die erste Suche erfolgt mit BM25.
Grund: Es ist am transparentesten und stärkste für die Suche nach Code/API‑Strings.
Die zweite Suche erfolgt mit voyage-code-3 Embedding.
Grund: Da die Abfrage ein Code‑Chunk ist, passt ein Code‑Retrieval‑Modell.
Die dritte Sortierung erfolgt mit rerank-2.5.
Grund: Um das echte Chunk und das passende JSONL unter den ähnlichen Kandidaten, die von BM25 und Embedding geliefert wurden, nach oben zu bringen.
Die abschließende Validierung erfolgt mit dem Qwen direct‑evidence validator.
Grund: Wenn es im JSONL keinen direkten String/Pattern‑Beweis gibt, der zum Chunk passt, muss er verworfen werden.Einzeilig zusammengefasst:
raw chunk 그대로 입력 → BM25 + code embedding 병렬 후보 생성 → reranker 재정렬 → Qwen 직접근거 검증 ist die richtige Antwort.
Es ist richtig, den Godot‑API‑Signal‑Extractor nicht zwingend einzufügen. Selbst wenn du es hinzufügst, solltest du es nur als „Punktbonus“ verwenden. Die Grundsuche sollte über raw‑Chunk‑basiertes BM25/Vector laufen, was deiner Absicht entspricht.