Spaces:
Running
Running
| import os | |
| import streamlit as st | |
| import subprocess | |
| import openai | |
| import PyPDF2 | |
| from langchain_community.vectorstores import FAISS | |
| from langchain.embeddings import HuggingFaceEmbeddings | |
| from openai import OpenAI | |
| from langchain_openai import ChatOpenAI | |
| from typing import List, Dict | |
| from langchain.schema import Document | |
| from langchain_experimental.text_splitter import SemanticChunker # module for chunking text | |
| import os | |
| # Load environment variables | |
| OPENAI_API_KEY = os.getenv("OPENAI_API") | |
| TOKEN=os.getenv('HF_TOKEN') | |
| subprocess.run(["huggingface-cli", "login", "--token", TOKEN, "--add-to-git-credential"]) | |
| class PDFChatbot: | |
| def __init__(self): | |
| self.azure_client = openai.OpenAI() | |
| self.conversation_history = [] | |
| self.pdf_content = "" | |
| self.faiss_index = self.build_faiss_index("data") | |
| def build_faiss_index(self, pdf_directory: str, chunk_size: int = 3000) -> FAISS: | |
| """Read PDFs, split into chunks, and build FAISS index.""" | |
| all_text = "" | |
| for filename in os.listdir(pdf_directory): | |
| if filename.lower().endswith(".pdf"): | |
| pdf_path = os.path.join(pdf_directory, filename) | |
| with open(pdf_path, "rb") as pdf_file: | |
| pdf_reader = PyPDF2.PdfReader(pdf_file) | |
| for page in pdf_reader.pages: | |
| page_text = page.extract_text() | |
| if page_text: | |
| all_text += page_text + "\n" | |
| # Split text into ~chunk_size character chunks | |
| words = all_text.split() | |
| chunks = [] | |
| current_chunk = [] | |
| current_length = 0 | |
| for word in words: | |
| if current_length + len(word) + 1 > chunk_size: | |
| if current_chunk: | |
| chunks.append(Document(page_content=" ".join(current_chunk))) | |
| current_chunk = [word] | |
| current_length = len(word) | |
| else: | |
| current_chunk.append(word) | |
| current_length += len(word) + 1 | |
| if current_chunk: | |
| chunks.append(Document(page_content=" ".join(current_chunk))) | |
| # Embed and index | |
| embedding_model = HuggingFaceEmbeddings(model_name='bkai-foundation-models/vietnamese-bi-encoder') | |
| faiss_index = FAISS.from_documents(chunks, embedding_model) | |
| return faiss_index | |
| def get_relevant_context(self, user_question: str) -> List[str]: | |
| """Query the FAISS index for the top relevant chunks.""" | |
| relevant_chunks = self.faiss_index.similarity_search(user_question, k=3) | |
| return "\n\n".join([doc.page_content for doc in relevant_chunks]) | |
| def chat_with_pdf(self, user_question: str, pdf_content: str) -> str: | |
| """Generate response using Azure OpenAI based on PDF content and user question.""" | |
| # Split PDF content into chunks | |
| # Get relevant context for the question | |
| relevant_context = self.get_relevant_context(user_question) | |
| # Prepare messages for the chat | |
| messages = [ | |
| { | |
| "role": "system", | |
| "content": """You are an experienced insurance agent assistant who helps customers understand their insurance policies and coverage details. Follow these guidelines: | |
| 1. Only provide information based on the PDF content provided | |
| 2. If the answer is not in the PDF, clearly state that the information is not available in the document | |
| 3. Provide clear, concise, and helpful responses in a professional manner | |
| 4. Always respond in Vietnamese using proper grammar and formatting | |
| 5. When possible, reference specific sections or clauses from the policy | |
| 6. Use insurance terminology appropriately but explain complex terms when necessary | |
| 7. Be empathetic and patient, as insurance can be confusing for customers | |
| 8. If asked about claims, coverage limits, deductibles, or policy terms, provide accurate information from the document | |
| 9. Always prioritize customer understanding and satisfaction | |
| 10. If multiple interpretations are possible, explain the different scenarios clearly | |
| Remember: You are here to help customers understand their insurance coverage better.""" | |
| }, | |
| { | |
| "role": "user", | |
| "content": f"""Insurance Document Content: | |
| {relevant_context} | |
| Customer Question: {user_question} | |
| Please provide a helpful response based on the insurance document content above.""" | |
| } | |
| ] | |
| # Add conversation history | |
| for msg in self.conversation_history[-6:]: # Keep last 6 messages for context | |
| messages.append(msg) | |
| # Get response from Azure OpenAI | |
| response = self.azure_client.chat.completions.create( | |
| model="gpt-4o-mini", | |
| messages=messages, | |
| max_tokens=800, #TODO | |
| temperature=0.7 | |
| ) | |
| bot_response = response.choices[0].message.content | |
| # Update conversation history | |
| self.conversation_history.append({"role": "user", "content": user_question}) | |
| self.conversation_history.append({"role": "assistant", "content": bot_response}) | |
| return bot_response | |
| def main(): | |
| st.set_page_config(page_title="Chatbot MB Ageas Life", page_icon="🛡️", layout="wide") | |
| st.title("🛡️ Chatbot tư vấn bảo hiểm của công ty bảo hiểm nhân thọ MB Ageas Life") | |
| # Initialize chatbot | |
| if 'chatbot' not in st.session_state: | |
| st.session_state.chatbot = PDFChatbot() | |
| st.session_state.pdf_processed = False | |
| st.session_state.chat_history = [] | |
| # Sidebar for PDF upload and settings | |
| # Clear conversation | |
| if st.button("Xóa lịch sử"): | |
| st.session_state.chatbot.conversation_history = [] | |
| st.session_state.chat_history = [] | |
| st.rerun() | |
| # Main chat interface | |
| st.header("💬 Hãy đặt câu hỏi cho tôi về gói bảo hiểm bạn quan tâm") | |
| # Display chat history | |
| for i, (question, answer) in enumerate(st.session_state.chat_history): | |
| with st.container(): | |
| st.markdown(f"**Câu hỏi:** {question}") | |
| st.markdown(f"**Trợ lý bảo hiểm:** {answer}") | |
| st.divider() | |
| # Chat input | |
| user_question = st.chat_input("Hãy đặt những câu hỏi về hợp đồng bảo hiểm cơ bản...") | |
| if user_question: | |
| with st.spinner("Đang đưa ra câu trả lời..."): | |
| # Get response from chatbot | |
| response = st.session_state.chatbot.chat_with_pdf( | |
| user_question, | |
| st.session_state.chatbot.pdf_content | |
| ) | |
| # Add to chat history | |
| st.session_state.chat_history.append((user_question, response)) | |
| # Display the new response | |
| st.markdown(f"**Câu hỏi:** {user_question}") | |
| st.markdown(f"**Trợ lý bảo hiểm:** {response}") | |
| else: | |
| # Show example questions | |
| st.subheader("Các câu hỏi bạn có thể hỏi:") | |
| st.markdown(""" | |
| - Giới hạn bảo hiểm cho thiệt hại tài sản của tôi là bao nhiêu? | |
| - Mức khấu trừ của tôi là bao nhiêu? | |
| - Những loại sự cố nào được bảo hiểm theo hợp đồng này? | |
| - Những gì không được bảo hiểm? | |
| - Làm thế nào để tôi nộp đơn yêu cầu bồi thường? | |
| - Quy trình giải quyết yêu cầu bồi thường như thế nào? | |
| - Tôi có những lựa chọn nào để thanh toán phí bảo hiểm? | |
| - Hợp đồng bảo hiểm của tôi hết hạn khi nào? | |
| - Bảo hiểm có bao gồm thiệt hại do lũ lụt không? | |
| - Tôi cần những giấy tờ gì khi nộp đơn yêu cầu bồi thường? | |
| """) | |
| # Thêm mẹo bảo hiểm | |
| st.subheader("💡 Mẹo về bảo hiểm") | |
| st.markdown(""" | |
| - Thường xuyên xem lại hợp đồng bảo hiểm để hiểu rõ quyền lợi của bạn | |
| - Lưu giữ tài liệu bảo hiểm ở nơi an toàn | |
| - Cập nhật quyền lợi bảo hiểm khi hoàn cảnh của bạn thay đổi | |
| - Ghi lại mọi sự cố ngay khi xảy ra | |
| - Liên hệ với đại lý bảo hiểm nếu bạn có bất kỳ câu hỏi nào | |
| """) | |
| if __name__ == "__main__": | |
| main() |