File size: 1,894 Bytes
9df46ad
2d6e389
9df46ad
2d6e389
 
9df46ad
 
 
 
2d6e389
 
 
9df46ad
 
 
2d6e389
9df46ad
 
2d6e389
9df46ad
 
2d6e389
9df46ad
 
2d6e389
9df46ad
 
2d6e389
9df46ad
 
 
2d6e389
9df46ad
 
2d6e389
9df46ad
 
 
2d6e389
9df46ad
 
 
2d6e389
9df46ad
2d6e389
9df46ad
 
 
 
2d6e389
9df46ad
2d6e389
9df46ad
 
 
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
import os
import faiss
from sentence_transformers import SentenceTransformer
from transformers import AutoTokenizer, AutoModelForCausalLM

DATA_PATH = "data/feng_family.txt"
INDEX_DIR = "index"
FAISS_PATH = os.path.join(INDEX_DIR, "family.faiss")
BLOCKS_PATH = os.path.join(INDEX_DIR, "blocks.txt")

embed_model = SentenceTransformer("BAAI/bge-small-zh-v1.5")

def build_index_if_needed():
    if os.path.exists(FAISS_PATH) and os.path.exists(BLOCKS_PATH):
        return

    with open(DATA_PATH, "r", encoding="utf-8") as f:
        text = f.read()

    blocks = [b.strip() for b in text.split("--- PERSON ---") if b.strip()]
    embeddings = embed_model.encode(blocks, normalize_embeddings=True)

    index = faiss.IndexFlatIP(embeddings.shape[1])
    index.add(embeddings)

    os.makedirs(INDEX_DIR, exist_ok=True)
    faiss.write_index(index, FAISS_PATH)

    with open(BLOCKS_PATH, "w", encoding="utf-8") as f:
        for b in blocks:
            f.write(b.replace("\n", " ") + "\n===\n")

# 启动时自动建索引(只会跑一次)
build_index_if_needed()

index = faiss.read_index(FAISS_PATH)
with open(BLOCKS_PATH, "r", encoding="utf-8") as f:
    blocks = f.read().split("===")

llm_name = "Qwen/Qwen2.5-1.5B"
tokenizer = AutoTokenizer.from_pretrained(llm_name)
model = AutoModelForCausalLM.from_pretrained(llm_name)

SYSTEM_PROMPT = "你是冯氏家谱机器人,只能根据家谱资料回答,没有记载就说未记载。"

def ask(question: str) -> str:
    q_emb = embed_model.encode([question], normalize_embeddings=True)
    _, I = index.search(q_emb, 1)
    context = blocks[I[0][0]]

    prompt = f"{SYSTEM_PROMPT}\n\n【家谱资料】\n{context}\n\n【问题】{question}\n回答:"

    inputs = tokenizer(prompt, return_tensors="pt")
    outputs = model.generate(**inputs, max_new_tokens=200)
    return tokenizer.decode(outputs[0], skip_special_tokens=True)