File size: 8,562 Bytes
e1ee9d9
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
47f7115
e1ee9d9
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
47f7115
e1ee9d9
47f7115
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
e1ee9d9
 
47f7115
e1ee9d9
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
47f7115
e1ee9d9
7e60e5a
e1ee9d9
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
47f7115
 
e1ee9d9
 
 
 
 
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
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
# app.py

import os
import gradio as gr
from dotenv import load_dotenv

# === All Imports ===
import datetime
import json
import requests
import pytz
from dateutil import parser
from typing import Optional, List, Dict

# === LangChain / LangGraph Imports ===
from langchain_core.messages import AIMessage
from langchain.tools import tool
from langchain_openai import ChatOpenAI
from langgraph.prebuilt import create_react_agent

# ==============================================================================
# PART 1: TOOL DEFINITIONS
# ==============================================================================
@tool
def get_horoscope(sign: str, date: str = None, language: str = "EN") -> str:
    """Fetches the horoscope for a given zodiac sign and date."""
    try:
        if date: date_obj = parser.parse(date)
        else: date_obj = datetime.datetime.now()
        formatted_date = date_obj.strftime("%d-%m-%Y")
        params = {"rashi": sign.upper(), "language": language, "day": formatted_date}
        url = "https://api.exaweb.in:3004/api/rashi"
        response = requests.get(url, params=params)
        response.raise_for_status()
        return json.dumps(response.json())
    except Exception as e: return f"Error in get_horoscope: {e}"

@tool
def get_date_panchang(date: str = None, data_language: str = "EN") -> str:
    """Fetches the Panchang data for a given date."""
    try:
        if not date: now = datetime.datetime.now()
        else: now = parser.parse(date)
        api_date = now.strftime("%d/%m/%y")
        url = f"https://api.exaweb.in:3004/api/panchang/daily?date={api_date}&app_language=EN&data_language={data_language}"
        headers = {"api_key": "anvl_bharat_cal123"}
        response = requests.get(url, headers=headers)
        response.raise_for_status()
        return json.dumps(response.json())
    except Exception as e: return f"Error in get_date_panchang: {e}"

@tool
def get_holidays(year: int = None, data_language: str = "EN") -> str:
    """Fetches holidays for a given year."""
    try:
        if not year: year = datetime.datetime.now().year
        params = {"data_language": data_language, "year": year}
        headers = {"api_key": "anvl_bharat_cal123"}
        response = requests.get("https://api.exaweb.in:3004/api/panchang/holiday", params=params, headers=headers)
        response.raise_for_status()
        return json.dumps(response.json())
    except Exception as e: return f"Error in get_holidays: {e}"

@tool
def get_monthly_festivals(year: Optional[int] = None, month: Optional[str] = None, data_language: str = "EN") -> str:
    """Fetches festival data for a specific month and year."""
    try:
        if not year: year = datetime.datetime.now().year
        if not month: month = datetime.datetime.now().strftime("%B").lower()
        else: month = month.lower()
        api_url = "https://api.exaweb.in:3004/api/panchang/festival"
        params = {"year": year, "month": month, "data_language": data_language}
        headers = {"api_key": "anvl_bharat_cal123"}
        response = requests.get(api_url, params=params, headers=headers)
        response.raise_for_status()
        return json.dumps(response.json())
    except Exception as e: return f"Error in get_monthly_festivals: {e}"

all_tools = [get_horoscope, get_date_panchang, get_holidays, get_monthly_festivals]

# ==============================================================================
# PART 2: SYSTEM PROMPT
# ==============================================================================
SYSTEM_PROMPT = """You are an expert astrological and calendar assistant. Your primary function is to use the provided tools to answer user queries accurately.

**Core Directives:**
1.  **Tool First:** You MUST use the provided tools to find information. Never answer from your own general knowledge. If the tools do not provide an answer, state that the information could not be found.
2.  **Language Match:** You MUST respond in the exact language of the user's query. You are proficient in English (EN), Hindi (HI), Bengali (BN), Gujarati (GU), Tamil (TA), Telugu (TE), Kannada (KN), Malayalam (ML), Marathi (MR), Oriya (OR), and Panjabi (PA).
3.  **Interpret, Don't Dump:** Your job is to interpret the JSON data returned by the tools and present it to the user in a clear, well-formatted, and human-readable way. Do not just output the raw JSON.

---

**Tool Usage and Data Interpretation Guide:**

**1. `get_horoscope`**
   - **When to Use:** Use this tool when a user asks for a horoscope for any zodiac sign (e.g., Aries, Leo, Gemini).
   - **Data Interpretation:** The tool returns a JSON object with keys like `prediction`, `monetary_gains`, `love_life`, `health`, `lucky_number`, and `lucky_color`. Format your response using clear headings for each of these categories.

**2. `get_date_panchang`**
   - **When to Use:** Use this tool when a user asks for the "Panchang," "Panchangam," or detailed daily astrological details for a specific date.
   - **Data Interpretation:** This tool returns a very large JSON object. **Do not dump the entire object.**
     - If the user asks for the general Panchang, summarize the most important elements: **Sunrise, Sunset, Tithi, Nakshatra, Yoga, and Karana**.
     - If the user asks for a specific detail (e.g., "What is Rahu Kalam today?"), find that specific key in the JSON (`Rahu Kalam`) and provide only that information.

**3. `get_holidays`**
   - **When to Use:** Use this tool for general queries about holidays within a specific **year**.
   - **Data Interpretation:** Present the holidays in a clean list format.

**4. `get_monthly_festivals`**
   - **When to Use:** Prefer this tool when a user asks for festivals in a specific **month**. It provides more detail than `get_holidays`.
   - **Data Interpretation:** Format the response as a list of festivals for that month, including the date for each.

---

**Final Response Style:**
Your final answer to the user should always be friendly, well-formatted, and directly address their question using only the data you retrieved from the tools.
"""

# ==============================================================================
# PART 3: MODEL INITIALIZATION
# ==============================================================================
load_dotenv()
SARVAM_API_KEY = os.getenv("SARVAM_API_KEY")

if not SARVAM_API_KEY:
    print("Warning: SARVAM_API_KEY secret not found.")

model = ChatOpenAI(
    model="sarvam-m",
    api_key=SARVAM_API_KEY,
    base_url="https://api.sarvam.ai/v1",
    temperature=0.2,
)
print("Sarvam AI model initialized successfully.")

# ==============================================================================
# PART 4: AGENT CREATION
# ==============================================================================
agent_app = create_react_agent(model=model, tools=all_tools, prompt=SYSTEM_PROMPT)
print("Pre-built ReAct agent created successfully.")

# ==============================================================================
# PART 5: GRADIO UI
# ==============================================================================
def get_agent_response(messages: list):
    """This function is called by the Gradio UI."""
    # Inject date context on the first turn
    if len(messages) == 1:
        now = datetime.datetime.now(pytz.timezone("Asia/Kolkata"))
        date_context = f"For context, today's date is {now.strftime('%A, %B %d, %Y')}."
        messages[0]['content'] = f"{messages[0]['content']} ({date_context})"
    
    inputs = {"messages": messages}
    final_response_content = ""

    try:
        for event in agent_app.stream(inputs, stream_mode="values"):
            response_messages = event.get('messages', [])
            if response_messages:
                final_message = response_messages[-1]
                if isinstance(final_message, AIMessage) and not final_message.tool_calls:
                    final_response_content = final_message.content
        return final_response_content
    except Exception as e:
        print(f"Error during agent execution: {e}")
        return "Sorry, an error occurred while processing your request."

# Create the Gradio Chat Interface with the fix
chatbot_ui = gr.ChatInterface(
    fn=get_agent_response,
    title="Jyotish AI Assistant",
    description="Ask about horoscopes, panchang, holidays, and festivals.",
    type="messages"
    # The 'examples' line has been removed to prevent the startup crash.
)

# Launch the Gradio app
chatbot_ui.launch()
print("Gradio UI is running.")