File size: 4,078 Bytes
9168fe7
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
import json
import os
import chromadb
from sentence_transformers import SentenceTransformer

def load_json(filepath):
    if not os.path.exists(filepath):
        print(f"[错误] 找不到文件: {filepath}")
        return {}
    with open(filepath, "r", encoding="utf-8") as f:
        return json.load(f)

def build_vector_db():
    # 推荐使用 m3e-base,对中文文本的检索效果非常好,且体积小
    print("[1] 正在加载嵌入模型...")
    embedder = SentenceTransformer('moka-ai/m3e-base', device='cuda')

    print("[2] 初始化本地 Chroma 向量数据库...")
    # 这会在当前目录下创建一个名为 "chroma_data" 的文件夹来持久化存储数据
    chroma_client = chromadb.PersistentClient(path="./chroma_data")
    
    # 创建或获取一个集合(Collection),相当于关系型数据库里的"表"
    collection = chroma_client.get_or_create_collection(name="mansus_lore")

    print("[3] 正在读取 JSON 数据...")
    hours_data = load_json("data/hours_merged.json")
    history_data = load_json("data/mansus_history_events_rag.json")

    documents = []   # 存储纯文本块
    metadatas = []   # 存储元数据(用于过滤和与图谱联动)
    ids = []         # 存储唯一 ID

    print("[4] 正在处理司辰 (Hours) 文本...")
    for hour in hours_data.get("hours", []):
        hour_id = hour.get("id", "")
        desc = hour.get("desc_cn", "")
        name = hour.get("name_cn", "")
        
        if not hour_id or not desc:
            continue
            
        documents.append(f"【司辰档案】{name}{desc}")
        metadatas.append({
            "type": "hour",
            "entity_id": hour_id,
            "entity_name": name
        })
        ids.append(f"doc_{hour_id}")

    print("[5] 正在处理漫宿历史事件 (History Events) 文本...")
    for era_name, era_obj in history_data.items():
        for event_title, event_obj in era_obj.get("events", {}).items():
            # 优先使用我们之前用大模型生成的精炼摘要
            summary = event_obj.get("summary_cn", "")
            if not summary:
                # 如果没有摘要,就把原段落拼起来
                summary = "\n".join(event_obj.get("paragraphs", []))
                
            if summary.strip():
                documents.append(f"【历史事件】{era_name} - {event_title}:\n{summary}")
                metadatas.append({
                    "type": "event",
                    "era": era_name,
                    "event_title": event_title
                })
                ids.append(f"doc_event_{event_title}")
                
            # 处理子事件 (h4)
            for sub_title, sub_obj in event_obj.get("subevents", {}).items():
                sub_summary = sub_obj.get("summary_cn", "")
                if not sub_summary:
                    sub_summary = "\n".join(sub_obj.get("paragraphs", []))
                
                if sub_summary.strip():
                    documents.append(f"【历史事件】{era_name} - {event_title} ({sub_title}):\n{sub_summary}")
                    metadatas.append({
                        "type": "subevent",
                        "era": era_name,
                        "parent_event": event_title,
                        "event_title": sub_title
                    })
                    ids.append(f"doc_subevent_{sub_title}")

    print(f"[6] 开始对 {len(documents)} 个文本块进行向量化并存入数据库 ...")
    # 批量进行向量化
    embeddings = embedder.encode(documents, show_progress_bar=True).tolist()

    # 批量存入 ChromaDB
    # 注意:如果数据量上万,建议分批次(Batch)存入。这里数据量在几百条左右,可以直接一次性插入。
    collection.upsert(
        documents=documents,
        embeddings=embeddings,
        metadatas=metadatas,
        ids=ids
    )

    print("[7] 向量库构建完成!数据已持久化保存在 ./chroma_data 目录。")

if __name__ == "__main__":
    build_vector_db()