import gradio as gr import json import os from google import genai from google.genai import types import requests from dotenv import load_dotenv # Load environment variables from .env file load_dotenv() # Initialize Google Gemini API GEMINI_API_KEY = os.getenv("GEMINI_API_KEY") client = genai.Client(api_key=GEMINI_API_KEY) # System instructions for the AI SYSTEM_INSTRUCTION = """You are an Islamic knowledge assistant specialized in the Quran. Your task is to: 1. Analyze the user's question about Islam or the Quran 2. Find relevant verses from the Quran that address their question, at most 5 verses 3. Provide thoughtful reasoning about how these verses relate to their question 4. Return your response in a specific JSON format with the fields: - reasoning (string explaining the relevance) - verses (array of objects with surah number, verse number, and brief explanation) - final_answer (string providing a comprehensive answer to the user's question based on the verses. Only answer from the verses, no additional information by yourself) Example: INPUT: What to eat? OUTPUT: { "reasoning": "The users prompt states 'What to eat?', so I need to find the verses which contain information on what can we eat and what we should avoid eating according to the Quran.", "verses": [ { "surah": 2, "verse": 168, "text": "O mankind! Eat of that which is lawful and wholesome in the earth, and follow not the footsteps of the devil. Lo! he is an open enemy for you." }, { "surah": 5, "verse": 4, "text": "Forbidden unto you [for food] are carrion and blood and swineflesh, and that which hath been dedicated unto any other than Allah, and the strangled, and the dead through beating, and the dead through falling from a height, and that which hath been killed by [the goring of] horns, and the devoured of wild beasts, saving that which ye make lawful [by the death-stroke], and that which hath been immolated unto idols. And [forbidden is it] that ye swear by the divining arrows. This is an abomination. This day are those who disbelieve in despair of [ever harming] your religion; so fear them not, fear Me! This day have I perfected your religion for you and completed My favour unto you, and have chosen for you as religion al-Islam. Whoso is forced by hunger, not by will, to sin: [for him] lo! Allah is Forgiving, Merciful." } ], "final_answer": "According to the Quran, Muslims should eat food that is lawful (halal) and wholesome. The Quran prohibits consuming carrion, blood, pork (swineflesh), and anything dedicated to other than Allah. It also forbids eating animals that have been strangled, beaten to death, killed by falling, gored to death, or partially eaten by wild animals (unless properly slaughtered before death). However, if one is forced by hunger and not by willful disobedience, Allah is Forgiving and Merciful." } Be precise with surah and verse numbers, using only numbers (not strings like "2:153").""" # Safety Settings SAFETY_SETTINGS = { types.HarmCategory.HARM_CATEGORY_HARASSMENT: types.HarmBlockThreshold.BLOCK_NONE, types.HarmCategory.HARM_CATEGORY_HATE_SPEECH: types.HarmBlockThreshold.BLOCK_NONE, types.HarmCategory.HARM_CATEGORY_SEXUALLY_EXPLICIT: types.HarmBlockThreshold.BLOCK_NONE, types.HarmCategory.HARM_CATEGORY_DANGEROUS_CONTENT: types.HarmBlockThreshold.BLOCK_NONE, } # Function to read and parse the Quran text from the file def load_quran_text(): try: quran_path = os.path.join(os.path.dirname(os.path.abspath(__file__)), "en.sahih.txt") with open(quran_path, 'r', encoding='utf-8') as file: quran_text = file.read() return quran_text except Exception as e: print(f"Error loading Quran text: {str(e)}") return "" # Load Quran text once when the app starts QURAN_TEXT = load_quran_text() # Function to get Quran verse with translation using Quran.com API def get_quran_verse(surah, verse): try: url = f"https://api.quran.com/api/v4/verses/by_key/{surah}:{verse}" params = { "language": "en", "words": False, "fields": "text_imlaei", "translations": "131" # 131 is the ID for Dr. Mustafa Khattab, The Clear Quran } response = requests.get(url, params=params) data = response.json() arabic_text = data["verse"]["text_imlaei"] translation = data["verse"]["translations"][0]["text"] return { "arabic": arabic_text, "translation": translation } except Exception as e: return { "arabic": f"Error retrieving verse {surah}:{verse}", "translation": f"Error: {str(e)}" } # Function to generate response using AI def generate_response(prompt): try: # Use custom API key if provided, otherwise use default api_key = GEMINI_API_KEY # Create a client with the appropriate API key current_client = genai.Client(api_key=api_key) # Append Quran text to the user's prompt full_prompt = f"{prompt}\n\nHere is the complete Quran text to use as reference:\n{QURAN_TEXT}" response = current_client.models.generate_content( model="gemini-2.0-flash", config=types.GenerateContentConfig( temperature=0, system_instruction=SYSTEM_INSTRUCTION, response_mime_type="application/json", safety_settings=[ types.SafetySetting( category=category, threshold=threshold ) for category, threshold in SAFETY_SETTINGS.items() ] ), contents=[full_prompt] ) response_text = response.text # Parse the JSON response result = json.loads(response_text) return result except Exception as e: return { "reasoning": f"Error generating response: {str(e)}", "verses": [] } # Function to validate and update API key def update_api_key(api_key): if not api_key: return "Using default API key" try: # Test the API key with a simple request test_client = genai.Client(api_key=api_key) test_client.models.list() return "✅ API key validated successfully" except Exception as e: return f"❌ Invalid API key: {str(e)}" # Gradio interface function def quran_helper(prompt): response = generate_response(prompt) verses = response.get("verses", []) final_answer = response.get("final_answer", "No final answer provided") # Format output for display output = f"## Summary\n{final_answer}\n\n" # Add disclaimer output += "> **Disclaimer:** This summary is AI-generated and may contain mistakes or misinterpretations. Always verify with original sources and consult qualified scholars for definitive religious guidance.\n\n" output += "## Relevant Verses\n" verse_details = [] for v in verses: surah = v.get("surah") verse = v.get("verse") explanation = v.get("text", "") if isinstance(surah, str) and ":" in surah: # Handle case where AI returns "surah:verse" format instead of separate fields parts = surah.split(":") surah = int(parts[0]) verse = int(parts[1]) # Get verse text and translation verse_data = get_quran_verse(surah, verse) verse_info = f"### Surah {surah}, Verse {verse}\n" verse_info += f"**Arabic:** {verse_data['arabic']}\n\n" verse_info += f"**Translation:** {verse_data['translation']}\n\n" verse_info += f"[View on Quran.com](https://quran.com/{surah}/{verse})\n\n" verse_details.append(verse_info) output += "\n".join(verse_details) return output # Create Gradio interface with gr.Blocks(theme="soft") as demo: gr.Markdown("# Quran Helper") gr.Markdown("Ask questions about Islam and get relevant verses from the Quran with explanations.") prompt_input = gr.Textbox( label="Enter your question about Islam or the Quran", placeholder="Example: What does the Quran say about patience?", lines=3 ) api_key_input = None submit_btn = gr.Button("Submit") output = gr.Markdown(label="Response") submit_btn.click(quran_helper, inputs=prompt_input, outputs=output) gr.Examples( examples=[ ["What does the Quran say about patience?"], ["How should Muslims treat their parents?"], ["What guidance does the Quran provide about honesty?"] ], inputs=prompt_input ) if __name__ == "__main__": demo.launch()