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)
|