| |
| """ |
| Build RAG index v2.0 — merged index combining: |
| 1. v1 embedding index (9,919 doc/kconfig/qa chunks) |
| 2. Source code function implementations (3,894 functions) |
| 3. Documentation/ RST files (1,633 chunks) |
| |
| All with sentence embeddings (all-MiniLM-L6-v2). |
| |
| Usage: python scripts/build_rag_index_v20.py |
| """ |
|
|
| import json, pickle, time |
| from pathlib import Path |
|
|
| PROJECT_ROOT = Path(__file__).resolve().parent.parent |
| RAG_INDEX_DIR = PROJECT_ROOT / "data" / "rag_index_v20" |
|
|
|
|
| def main(): |
| chunks = [] |
| |
| |
| v1_path = PROJECT_ROOT / "data" / "rag_index_emb" / "chunks.jsonl" |
| if v1_path.exists(): |
| with open(v1_path) as f: |
| for line in f: |
| c = json.loads(line) |
| c["_source_group"] = "v1_doc" |
| chunks.append(c) |
| print(f"v1 doc chunks: {sum(1 for c in chunks if c['_source_group']=='v1_doc')}") |
| |
| |
| src_path = PROJECT_ROOT / "data" / "rag_index_source_emb" / "chunks.jsonl" |
| if src_path.exists(): |
| with open(src_path) as f: |
| for line in f: |
| c = json.loads(line) |
| c["_source_group"] = "source_code" |
| chunks.append(c) |
| print(f"Source code chunks: {sum(1 for c in chunks if c['_source_group']=='source_code')}") |
| |
| print(f"\nTotal chunks: {len(chunks)}") |
| |
| |
| seen = set() |
| unique_chunks = [] |
| for c in chunks: |
| h = hash(c.get("content", "")[:300]) |
| if h not in seen: |
| seen.add(h) |
| unique_chunks.append(c) |
| print(f"After dedup: {len(unique_chunks)} chunks") |
| |
| |
| print("\nLoading embedding model (all-MiniLM-L6-v2)...", flush=True) |
| from sentence_transformers import SentenceTransformer |
| model = SentenceTransformer("all-MiniLM-L6-v2") |
| print(" Model loaded", flush=True) |
| |
| texts = [c["content"] for c in unique_chunks] |
| |
| print(f"Encoding {len(texts)} chunks...", flush=True) |
| start = time.time() |
| embeddings = model.encode(texts, show_progress_bar=True, batch_size=64) |
| elapsed = time.time() - start |
| print(f" Encoded {len(embeddings)} embeddings in {elapsed:.1f}s") |
| print(f" Embedding dimension: {embeddings.shape[1]}") |
| |
| |
| RAG_INDEX_DIR.mkdir(parents=True, exist_ok=True) |
| |
| with open(RAG_INDEX_DIR / "chunks.jsonl", "w") as f: |
| for c in unique_chunks: |
| f.write(json.dumps(c, ensure_ascii=False) + "\n") |
| |
| with open(RAG_INDEX_DIR / "embeddings.pkl", "wb") as f: |
| pickle.dump(embeddings, f) |
| |
| with open(RAG_INDEX_DIR / "model_name.txt", "w") as f: |
| f.write("all-MiniLM-L6-v2") |
| |
| |
| from collections import Counter |
| type_counts = Counter(c.get("type", "unknown") for c in unique_chunks) |
| source_counts = Counter(c.get("_source_group", "unknown") for c in unique_chunks) |
| |
| print(f"\nIndex saved to {RAG_INDEX_DIR}/") |
| print(f" chunks.jsonl: {len(unique_chunks)} chunks") |
| print(f" embeddings.pkl: {embeddings.shape}") |
| print(f"\nBy source group:") |
| for k, v in source_counts.most_common(): |
| print(f" {k}: {v}") |
| print(f"\nBy type:") |
| for k, v in type_counts.most_common(): |
| print(f" {k}: {v}") |
|
|
|
|
| if __name__ == "__main__": |
| main() |
|
|