| import os | |
| import requests | |
| from retriever import retrieve_docs | |
| from langchain_community.embeddings import HuggingFaceEmbeddings | |
| from numpy import dot | |
| from numpy.linalg import norm | |
| API_KEY = "AIzaSyClqQssVMjt02qKrGKnghYAK9RkGf0lkS4" | |
| def filter_relevant_docs(docs, query, top_k=3): | |
| embeddings = HuggingFaceEmbeddings(model_name="sentence-transformers/all-MiniLM-L6-v2") | |
| query_embedding = embeddings.embed_query(query) | |
| scores = [] | |
| for doc in docs: | |
| doc_embedding = embeddings.embed_query(doc.page_content) | |
| cosine_sim = dot(query_embedding, doc_embedding) / (norm(query_embedding) * norm(doc_embedding)) | |
| scores.append((doc, cosine_sim)) | |
| scores.sort(key=lambda x: x[1], reverse=True) | |
| return [doc for doc, _ in scores[:top_k]] | |
| def format_sources(docs): | |
| sources = set() | |
| for doc in docs: | |
| section = doc.metadata.get("section") | |
| if section: | |
| sources.add(section.strip()) | |
| else: | |
| filename = os.path.basename(doc.metadata.get("source", "Nguồn không xác định")) | |
| sources.add(filename) | |
| return "\n".join(f"- {src}" for src in sorted(sources)) | |
| def answer_query(query, model="Gemini Pro", temperature=0.2): | |
| all_docs = retrieve_docs(query) | |
| if not all_docs: | |
| return "Không tìm thấy tài liệu liên quan để trả lời.", [] | |
| docs = filter_relevant_docs(all_docs, query) | |
| context = "\n\n".join([doc.page_content for doc in docs]) | |
| prompt = f"""Dựa trên tài liệu sau, hãy trả lời câu hỏi theo phong cách trang trọng, lịch sự và chuyên nghiệp: | |
| {context} | |
| Câu hỏi: {query} | |
| Yêu cầu: | |
| - Sử dụng từ ngữ lịch sự ("Bạn cần...", "Vui lòng...", "Sau khi...") | |
| - Không sử dụng từ nói miệng như "nhé", "nha", "ok". | |
| - Câu trúc câu đầy đủ, rõ ràng. | |
| - Chỉ trả lời dựa trên thông tin trong tài liệu. Nếu không tìm thấy thông tin liên quan, trả lời: "Thông tin không có trong tài liệu được cung cấp." | |
| - Không tự thêm "Nguồn tham khảo" trong phần trả lời. | |
| Trả lời:""" | |
| url = f"https://generativelanguage.googleapis.com/v1/models/gemini-1.5-pro:generateContent?key={API_KEY}" | |
| headers = {"Content-Type": "application/json"} | |
| payload = { | |
| "contents": [{"parts": [{"text": prompt}]}], | |
| "generationConfig": {"temperature": temperature} | |
| } | |
| response = requests.post(url, headers=headers, json=payload) | |
| data = response.json() | |
| try: | |
| answer = data['candidates'][0]['content']['parts'][0]['text'] | |
| except Exception as e: | |
| print("🔴 Response từ Gemini:", data) | |
| answer = "Lỗi khi gọi Gemini API: " + str(e) | |
| return answer, docs | |