import streamlit as st import os from langchain_huggingface import HuggingFaceEmbeddings from langchain_community.vectorstores import FAISS from langchain.memory import ConversationBufferMemory from langchain.chains import ConversationalRetrievalChain from langchain_groq import ChatGroq # Changed to import ChatGroq from langchain.prompts import ChatPromptTemplate # Import the new dynamic template components from htmlTemplates import css, user_template, get_bot_template, BOT_AVATARS_BASE64 # ------------------- Dynamic Bot Names ------------------- BOT_NAMES = { "Khamenei": "حاجاقا محسنی", "Sistani": "حاجاقا جوادی", "Golpaygani": "حاجاقا محمدی", } # ------------------- Conversation Chain Function ------------------- def get_conversation_chain(vectorstore, llm): memory = ConversationBufferMemory( memory_key='chat_history', return_messages=True ) return ConversationalRetrievalChain.from_llm( llm=llm, retriever=vectorstore.as_retriever(), memory=memory, ) # ------------------- Classify Question ------------------- def classify_question(question, llm): prompt = ChatPromptTemplate.from_template(""" متن زیر را بررسی کن و فقط یکی از این سه برچسب را برگردان: - greeting: اگر متن سلام و احوال‌پرسی یا جملات دوستانه است - islamic_fiqh: اگر پرسش درباره احکام شرعی و فقهی اسلام است - irrelevant: اگر غیر از این دو بود متن: {question} برچسب: """) chain = prompt | llm result = chain.invoke({"question": question}) return result.content.strip().lower() # ------------------- Generate Friendly Response ------------------- def generate_friendly_response(question, label, llm, selected_source_english): bot_name = BOT_NAMES.get(selected_source_english, "پاسخگوی شما") if "greeting" in label: prompt = ChatPromptTemplate.from_template(f""" کاربر به شما سلام یا احوال‌پرسی کرده است. نام شما {bot_name} هست. متن کاربر: {{question}} """) else: # irrelevant prompt = ChatPromptTemplate.from_template(f""" کاربر پرسشی غیرمرتبط با احکام شرعی پرسیده است. تو به عنوان {bot_name} مودبانه و دوستانه به او بگویید که وظیفه‌ی شما فقط پاسخ به پرسش‌های شرعی است و او را به مطرح کردن یک سؤال دینی تشویق کنید. متن کاربر: {{question}} """) chain = prompt | llm result = chain.invoke({"question": question}) return result.content.strip() # ------------------- Handle User Input (Logic Only) ------------------- def handle_userinput(user_question): if st.session_state.conversation is None: st.warning("منابع هنوز آماده نشده‌اند.") return st.session_state.messages.append({"role": "user", "content": user_question}) label = classify_question(user_question, st.session_state.llm) if "islamic_fiqh" in label: response = st.session_state.conversation({'question': user_question}) bot_reply = response['answer'] else: bot_reply = generate_friendly_response(user_question, label, st.session_state.llm, st.session_state.selected_source_english) st.session_state.messages.append({"role": "bot", "content": bot_reply}) # ------------------- Main Streamlit App ------------------- def main(): st.set_page_config(page_title="شیخ جی پی تی", page_icon=":mosque:") st.write(css, unsafe_allow_html=True) st.markdown( "

پاسخگوی احکام شرعی 🕋

", unsafe_allow_html=True ) if "conversation" not in st.session_state: st.session_state.conversation = None if "messages" not in st.session_state: st.session_state.messages = [] if "llm" not in st.session_state: # Changed LLM to use Groq API with ChatGroq st.session_state.llm = ChatGroq( model_name="llama-3.1-8b-instant", temperature=0.2, api_key=os.environ["GROQ_API_KEY"] # Changed to use GROQ_API_KEY ) if "selected_source_english" not in st.session_state: st.session_state.selected_source_english = "Khamenei" current_bot_avatar_base64 = BOT_AVATARS_BASE64.get(st.session_state.selected_source_english) bot_template_with_avatar = get_bot_template(current_bot_avatar_base64) for msg in st.session_state.messages: if msg["role"] == "user": st.write(user_template.replace("{{MSG}}", msg["content"]), unsafe_allow_html=True) else: st.write(bot_template_with_avatar.replace("{{MSG}}", msg["content"]), unsafe_allow_html=True) if user_question := st.chat_input("سؤال شرعی خود را اینجا مطرح کنید..."): handle_userinput(user_question) st.rerun() with st.sidebar: st.subheader("منابع فقهی") SOURCE_MAPPINGS = { "آیت الله خامنه‌ای": "Khamenei", "آیت الله سیستانی": "Sistani", "آیت الله گلپایگانی": "Golpaygani" } persian_options = list(SOURCE_MAPPINGS.keys()) current_persian_name = next( (key for key, value in SOURCE_MAPPINGS.items() if value == st.session_state.selected_source_english), persian_options[0] ) selected_source_persian = st.selectbox( "مرجع تقلید خود را انتخاب کنید:", persian_options, index=persian_options.index(current_persian_name) ) selected_source_english = SOURCE_MAPPINGS[selected_source_persian] if st.session_state.selected_source_english != selected_source_english: st.session_state.selected_source_english = selected_source_english st.session_state.conversation = None st.session_state.messages = [] st.rerun() if st.session_state.conversation is None: placeholder = st.empty() placeholder.info(f"⏳ در حال بارگذاری منابع {selected_source_persian}...") try: embeddings = HuggingFaceEmbeddings( model_name="heydariAI/persian-embeddings", model_kwargs={'trust_remote_code': True}, cache_folder="/tmp/hf_cache" ) vector_path = f"Resources/{st.session_state.selected_source_english}/faiss_index" vectorstore = FAISS.load_local( vector_path, embeddings, allow_dangerous_deserialization=True ) st.session_state.conversation = get_conversation_chain(vectorstore, st.session_state.llm) placeholder.success( f"✅ منابع {selected_source_persian} آماده شدند. اکنون می‌توانید سؤال بپرسید.") except Exception as e: placeholder.error(f"⚠️ خطا در بارگذاری منابع: {e}") else: st.success(f"✅ منابع {selected_source_persian} بارگذاری شده‌اند") if __name__ == '__main__': main()