Godot 공식문서 RAG 분류기 스키마와 아키텍처
작성일: 2026 년 6 월 21 일
목적
Godot 공식문서 전체 수집본을 JSONL -> PostgreSQL -> Retriever -> Validator -> Qwen 3.6 흐름으로 연결하기 위한 기준 아키텍처를 정리한다. 이 문서는 바로 학습 데이터를 만들기 위한 구현 문서가 아니라, outputs/godot_docs_full/pages에 이미 모아둔 공식문서 Markdown을 어떤 형태로 구조화하고 검색 가능한 근거 DB로 만들지 정의하는 설계 기준이다.

현재 입력 데이터
공식문서 수집 결과는 저장소의 outputs/godot_docs_full 아래에 있다.
| 경로 | 역할 |
|---|---|
outputs/godot_docs_full/pages/ |
Godot 공식문서 페이지별 Markdown 원본 |
outputs/godot_docs_full/manifest.json |
원본 URL, 로컬 파일 경로, 수집 상태, 바이트 크기 |
outputs/godot_docs_full/summary.json |
전체 수집 카운트와 검증 요약 |
outputs/godot_docs_full/urls.txt |
실제 수집 URL 목록 |
outputs/godot_docs_full/searchindex_urls.txt |
Sphinx search index에서 복원한 목표 URL 목록 |
outputs/godot_docs_full/failed.json |
수집 실패 목록 |
outputs/godot_docs_full/missing_from_searchindex.txt |
search index 기준 누락 목록 |
현재 기준선:
| 항목 | 값 |
|---|---|
| Search index target pages | 1568 |
| Collected pages | 1570 |
| Page files | 1570 |
| Failed fetches | 0 |
| Missing from search index | 0 |
전체 파이프라인
crawler가 Godot 공식문서를 인터넷에서 수집한다.- 수집 결과를 페이지 단위 Markdown으로 저장한다.
- Markdown을 정규화하고 메타데이터를 붙여 JSONL 레코드로 변환한다.
- JSONL을 PostgreSQL에 주입한다.
- PostgreSQL은 문서 청크, API 매핑, 라벨 프로토타입을 분리해서 저장한다.
- 사용자가 Godot 소스 코드 분석을 요청하면 AST Parser가 프로젝트 코드를 구조화한다.
- Retriever가 사용자 질문과 AST 분석 결과를 기준으로 PostgreSQL에서 근거를 검색한다.
- Validator가 질문, AST 결과, 검색 근거를 묶어 Qwen 3.6에 전달한다.
- Qwen 3.6은 최종 판정자가 아니라, 검증된 근거를 사용해 답변을 정리한다.
- Validator가 응답의 근거/형식/금지 패턴을 확인한 뒤 사용자에게 반환한다.
Markdown에서 JSONL로 변환
pages/*.md는 사람이 읽기 좋은 페이지 원본이고, RAG에는 너무 큰 단위다. 따라서 변환 스크립트는 페이지를 섹션/API 멤버/예제 단위로 쪼개고, 원본 URL과 문서 종류를 함께 보존해야 한다.
공통 정규화 규칙
| 단계 | 처리 |
|---|---|
| 파일 로드 | manifest.json의 file, url, status, bytes를 기준으로 Markdown을 읽는다. |
| 본문 정리 | 반복 헤더, Sphinx UI 텍스트, 깨진 앵커 문자, 과도한 공백을 제거한다. |
| 문서 타입 분류 | URL과 경로를 기준으로 class_reference, tutorial, migration, engine_details, about, other로 나눈다. |
| 섹션 분리 | 제목 계층과 Godot class reference 패턴을 기준으로 청크 후보를 만든다. |
| 코드 블록 보존 | GDScript, C#, shader, CLI 예제는 본문에서 제거하지 않고 code_blocks에 별도 보존한다. |
| provenance 부여 | 모든 레코드에 원본 URL, 파일 경로, 원본 해시, 변환 스크립트 버전을 남긴다. |
JSONL 산출물
| 파일 | 목적 | 대상 테이블 |
|---|---|---|
work/godot_rag/jsonl/docs_chunks.jsonl |
공식문서 설명/튜토리얼/레퍼런스 검색용 청크 | docs_chunks |
work/godot_rag/jsonl/api_mapping.jsonl |
Godot 3 -> 4 API 변경, rename, deprecation, replacement 규칙 | api_mapping |
work/godot_rag/jsonl/label_prototypes.jsonl |
분류/변환/거부/수정 예시 프로토타입 | label_prototypes |
work/godot_rag/jsonl/ingest_report.jsonl |
변환 중 경고, 스킵, 품질 점검 로그 | DB 주입 전 검증용 |
docs_chunks.jsonl 스키마
{
"chunk_id": "godot-stable:classes/class_node.html#description:0001",
"doc_version": "stable",
"source_url": "https://docs.godotengine.org/en/stable/classes/class_node.html",
"source_file": "outputs/godot_docs_full/pages/classes__class_node__....md",
"source_sha256": "...",
"doc_type": "class_reference",
"symbol": "Node",
"section_path": ["Node", "Description"],
"heading": "Description",
"content": "Nodes are Godot's building blocks...",
"code_blocks": [],
"language_tags": ["gdscript"],
"godot_version_tags": ["4.x", "stable"],
"api_symbols": ["Node", "_ready", "_process", "queue_free"],
"token_count": 420,
"metadata": {
"status": "copied_old",
"bytes": 12345
}
}필수 필드:
| 필드 | 설명 |
|---|---|
chunk_id |
재실행해도 바뀌지 않는 결정적 ID |
doc_version |
stable, 4.6 등 문서 버전 |
source_url |
공식문서 원본 URL |
source_file |
저장소 안 Markdown 경로 |
source_sha256 |
원본 Markdown 해시 |
doc_type |
문서 유형 |
symbol |
class/API 문서일 때 대표 심볼 |
section_path |
제목 계층 |
content |
검색과 임베딩 대상 본문 |
code_blocks |
본문에서 추출한 코드 블록 배열 |
api_symbols |
본문에서 감지한 Godot API 심볼 |
api_mapping.jsonl 스키마
{
"mapping_id": "godot3-to-4:kinematicbody2d-to-characterbody2d",
"source_api": "KinematicBody2D",
"target_api": "CharacterBody2D",
"change_type": "rename_or_replacement",
"godot_from": "3.x",
"godot_to": "4.x",
"confidence": "verified_from_docs",
"evidence_chunk_ids": [
"godot-stable:tutorials/migrating/upgrading_to_godot_4.html#..."
],
"match_terms": ["KinematicBody2D", "CharacterBody2D"],
"notes": "Godot 4 character movement node replacement candidate.",
"negative_patterns": ["do not suggest KinematicBody2D for Godot 4 projects"]
}원칙:
| 항목 | 기준 |
|---|---|
confidence |
공식문서 근거가 있으면 verified_from_docs, 규칙 후보는 candidate로 둔다. |
| 자동 추출 | migration 문서와 class reference에서 후보를 만들 수 있다. |
| 승인 기준 | 학습/라벨링에 쓰는 규칙은 사람이 검토한 항목만 approved 상태로 승격한다. |
| exact index | source_api, target_api, match_terms는 정확 검색 대상이다. |
label_prototypes.jsonl 스키마
{
"prototype_id": "label:godot3-api-in-godot4:kinematicbody2d",
"label": "godot3_api_in_godot4",
"task_type": "version_classification",
"input_pattern": "extends KinematicBody2D",
"expected_finding": "Godot 3 style physics body API detected.",
"recommended_action": "Use CharacterBody2D or CharacterBody3D depending on project dimension.",
"evidence_mapping_ids": [
"godot3-to-4:kinematicbody2d-to-characterbody2d"
],
"evidence_chunk_ids": [],
"severity": "high",
"validator_rules": {
"requires_ast_symbol": "KinematicBody2D",
"forbidden_answer_terms": ["KinematicBody2D is recommended in Godot 4"]
}
}라벨 후보:
| 라벨 | 의미 |
|---|---|
godot4_valid_api |
Godot 4 기준으로 유효한 API 사용 |
godot3_api_in_godot4 |
Godot 4 프로젝트에 Godot 3 API가 섞임 |
deprecated_or_removed_api |
제거/폐기 API 사용 |
migration_required |
Godot 3 -> 4 변환 필요 |
ambiguous_version_signal |
버전 판단 근거가 부족하거나 충돌 |
non_godot_noise |
Python/웹/Unity 등 Godot과 무관한 데이터 |
unsafe_or_obfuscated_code |
난독화, 제어문자, 악성 의심 코드 |
PostgreSQL 스키마 초안
PostgreSQL은 pgvector를 사용하는 것을 기본 전제로 둔다. 키워드 검색은 tsvector 또는 trigram index를 함께 사용한다.
docs_chunks
| 컬럼 | 타입 | 설명 |
|---|---|---|
id |
bigserial primary key |
내부 ID |
chunk_id |
text unique not null |
JSONL의 결정적 ID |
doc_version |
text not null |
문서 버전 |
source_url |
text not null |
공식문서 URL |
source_file |
text not null |
Markdown 파일 경로 |
source_sha256 |
text not null |
원본 해시 |
doc_type |
text not null |
문서 유형 |
symbol |
text |
대표 API/class 심볼 |
section_path |
jsonb not null |
제목 계층 |
heading |
text |
현재 청크 제목 |
content |
text not null |
검색 대상 본문 |
code_blocks |
jsonb not null default '[]' |
코드 블록 |
api_symbols |
text[] not null default '{}' |
추출 심볼 |
metadata |
jsonb not null default '{}' |
기타 메타데이터 |
embedding |
vector |
임베딩 |
search_tsv |
tsvector |
키워드 검색 |
created_at |
timestamptz default now() |
주입 시각 |
인덱스:
| 인덱스 | 목적 |
|---|---|
unique(chunk_id) |
중복 주입 방지 |
ivfflat/hnsw(embedding) |
의미 기반 검색 |
gin(search_tsv) |
키워드 검색 |
gin(api_symbols) |
API 심볼 필터 |
btree(doc_type, symbol) |
class/API 문서 필터 |
api_mapping
| 컬럼 | 타입 | 설명 |
|---|---|---|
id |
bigserial primary key |
내부 ID |
mapping_id |
text unique not null |
결정적 ID |
source_api |
text not null |
이전/문제 API |
target_api |
text |
권장 API |
change_type |
text not null |
rename, removed, behavior_change 등 |
godot_from |
text |
출발 버전 |
godot_to |
text |
목표 버전 |
confidence |
text not null |
근거 수준 |
status |
text not null default 'candidate' |
candidate, approved, rejected |
evidence_chunk_ids |
text[] not null default '{}' |
공식문서 근거 청크 |
match_terms |
text[] not null default '{}' |
검색 키워드 |
notes |
text |
설명 |
negative_patterns |
jsonb not null default '[]' |
금지 패턴 |
인덱스:
| 인덱스 | 목적 |
|---|---|
unique(mapping_id) |
중복 방지 |
btree(source_api) |
exact lookup |
btree(target_api) |
역방향 lookup |
gin(match_terms) |
키워드 검색 |
btree(status, confidence) |
승인 규칙 필터 |
label_prototypes
| 컬럼 | 타입 | 설명 |
|---|---|---|
id |
bigserial primary key |
내부 ID |
prototype_id |
text unique not null |
결정적 ID |
label |
text not null |
분류 라벨 |
task_type |
text not null |
classification, migration_fix, patch_generation 등 |
input_pattern |
text not null |
감지 패턴 |
expected_finding |
text not null |
기대 판정 |
recommended_action |
text |
권장 조치 |
evidence_mapping_ids |
text[] not null default '{}' |
API 매핑 근거 |
evidence_chunk_ids |
text[] not null default '{}' |
문서 청크 근거 |
severity |
text not null |
low, medium, high |
validator_rules |
jsonb not null default '{}' |
검증 규칙 |
embedding |
vector |
유사 사례 검색 |
search_tsv |
tsvector |
키워드 검색 |
인덱스:
| 인덱스 | 목적 |
|---|---|
unique(prototype_id) |
중복 방지 |
btree(label, task_type) |
라벨별 조회 |
ivfflat/hnsw(embedding) |
유사 라벨 검색 |
gin(search_tsv) |
키워드 검색 |
AST Parser 입력/출력
AST Parser는 사용자 소스 코드를 LLM에게 바로 넘기기 전에 검색 가능한 구조로 바꾼다. 초기 대상은 .gd, .tscn, project.godot이다.
입력
| 입력 | 설명 |
|---|---|
| 사용자 질문 | 예: "이 프로젝트가 Godot 4 기준으로 안전한지 봐줘" |
| 소스 코드 파일 | .gd, .tscn, .tres, project.godot |
| 프로젝트 구조 | 파일 경로, 씬 연결, 리소스 경로 |
출력 스키마
{
"project_id": "local-analysis-...",
"godot_project": {
"config_version": 5,
"features": ["4.4", "Forward Plus"]
},
"files": [
{
"path": "scripts/player.gd",
"language": "gdscript",
"extends": "CharacterBody2D",
"class_name": "Player",
"symbols": ["CharacterBody2D", "Input", "move_and_slide"],
"annotations": ["@onready"],
"version_signals": ["godot4_annotation_syntax"],
"diagnostics": []
}
],
"version_evidence": {
"godot4": ["config_version=5", "@onready"],
"godot3": []
}
}초기 추출 필드:
| 필드 | 목적 |
|---|---|
extends |
Node/API 버전 판단 |
class_name |
프로젝트 내부 심볼 매핑 |
annotations |
@onready, @export 등 Godot 4 신호 |
legacy_keywords |
onready var, export var, KinematicBody 등 Godot 3 신호 |
method_calls |
문서 검색과 API 매핑 조회 |
scene_dependencies |
씬/스크립트 연결 검증 |
resource_paths |
누락 리소스와 에셋 연결 검증 |
Retriever 동작
Retriever는 LLM보다 먼저 근거를 선택하는 계층이다.
- 사용자 질문에서 의도와 대상 태스크를 추출한다.
- AST Parser 결과에서 API 심볼, 버전 신호, 파일 경로를 가져온다.
api_mapping에서 exact lookup을 먼저 수행한다.docs_chunks에서 API 심볼 필터 + 키워드 검색 + 벡터 검색을 함께 수행한다.label_prototypes에서 유사 라벨과 검증 규칙을 가져온다.- 검색 결과를 근거 번들로 정렬한다.
근거 번들:
{
"query_id": "analysis-...",
"task_type": "version_classification",
"ast_summary": {},
"doc_evidence": [],
"api_mapping_evidence": [],
"label_evidence": [],
"retrieval_scores": {
"exact_api_hits": 2,
"keyword_hits": 8,
"vector_hits": 12
}
}Validator와 Qwen 3.6 역할 분리
Qwen 3.6은 검색된 근거를 읽고 답변을 정리하는 모델이다. 최종 라벨, 근거 채택, 금지 패턴 검증은 Validator가 담당한다.
| 구성요소 | 책임 |
|---|---|
| Retriever | 관련 공식문서/API 매핑/라벨 근거 검색 |
| Validator | 근거 누락, 금지 패턴, 출력 JSON 형식 검증 |
| Qwen 3.6 | 사용자에게 읽히는 설명, 수정 방향, 코드 제안 정리 |
Validator가 확인할 항목:
| 항목 | 기준 |
|---|---|
| 근거 ID 존재 | 답변에 사용한 문서/매핑/라벨 ID가 실제 검색 결과에 있어야 한다. |
| Godot 4 기준 | Godot 4 프로젝트에 Godot 3 API를 권장하지 않아야 한다. |
| 불확실성 표시 | 근거가 부족하면 확정 판정을 금지하고 ambiguous_version_signal로 둔다. |
| 코드 제안 검증 | 제안 코드가 감지된 프로젝트 차원 2D/3D와 충돌하지 않아야 한다. |
| JSON 형식 | 내부 파이프라인 출력은 파싱 가능한 JSON이어야 한다. |
주입 순서
outputs/godot_docs_full/summary.json과failed.json을 확인한다.manifest.json과pages/*.md를 로드한다.- Markdown 정규화 리포트를 만든다.
docs_chunks.jsonl을 생성한다.- migration/class 문서에서
api_mapping.jsonl후보를 생성한다. - 승인된 규칙과 대표 사례로
label_prototypes.jsonl을 생성한다. - JSONL 스키마 검증을 통과한 레코드만 PostgreSQL에 upsert한다.
- 임베딩을 생성하고 vector index를 갱신한다.
- 키워드 index와 exact index를 갱신한다.
- 샘플 질문으로 Retriever 결과를 검증한다.
품질 검증 체크리스트
| 단계 | 통과 기준 |
|---|---|
| 수집 검증 | failed_count = 0, missing_from_searchindex = 0 |
| Markdown 정규화 | 빈 청크 없음, 원본 URL 보존 |
| JSONL 검증 | 모든 줄이 JSON parse 가능, 필수 필드 존재 |
| 중복 검증 | chunk_id, mapping_id, prototype_id 중복 없음 |
| 근거 검증 | api_mapping.evidence_chunk_ids가 실제 docs_chunks에 존재 |
| 검색 검증 | 대표 API 질문에서 exact hit와 docs hit가 함께 반환 |
| 응답 검증 | Qwen 응답이 근거 없는 단정과 Godot 3 API 권장을 하지 않음 |
구현 우선순위
pages/*.md구조 분석 리포트 작성docs_chunks.jsonl변환 스크립트 작성- JSONL 스키마 검증 스크립트 작성
- PostgreSQL DDL 작성
docs_chunks주입과 검색 검증api_mapping후보 생성과 수동 승인 흐름 작성label_prototypes초기 라벨 세트 작성- AST Parser 최소 필드 추출
- Retriever 근거 번들 출력
- Validator + Qwen 3.6 응답 정리 루프 연결
핵심 원칙
- 공식문서 원본 Markdown은 수정하지 않고 보존한다.
- JSONL은 재생성 가능한 중간 산출물로 둔다.
- DB에는 원본 경로, 원본 URL, 해시, 변환 스크립트 버전을 반드시 남긴다.
- LLM이 라벨을 발명하지 못하게 한다.
- Godot 3/4 판정은 AST 신호, API 매핑, 공식문서 근거를 조합해서 한다.
- 불확실한 후보는 학습 데이터로 바로 쓰지 않고
candidate상태에 둔다. - Qwen 3.6은 답변 정리자이며, 판정 기준은 Retriever와 Validator가 가진다.
다음 작업
다음 단계는 outputs/godot_docs_full/pages의 Markdown 구조를 표본 분석하는 것이다. 특히 class reference, migration, tutorial 문서가 서로 다른 구조를 가지므로 하나의 청킹 규칙으로 밀어붙이지 않고 문서 타입별 청킹 전략을 먼저 확정해야 한다.