wearevenom commited on
Commit
d2cd3e3
·
verified ·
1 Parent(s): 3434ef3

Update fapi.py

Browse files
Files changed (1) hide show
  1. fapi.py +190 -171
fapi.py CHANGED
@@ -1,171 +1,190 @@
1
- from fastapi import FastAPI, HTTPException
2
- from fastapi.middleware.cors import CORSMiddleware
3
- from fastapi.responses import JSONResponse
4
- from pydantic import BaseModel
5
- from agents import coordinator
6
- from google.adk.sessions import InMemorySessionService
7
- from constants import INSTITUTE_MAPPING, BRANCH_MAPPING
8
- from google.adk.tools import google_search
9
- from google.adk.runners import Runner
10
- from google.genai import types # Add this import for Content and Part
11
- from dotenv import load_dotenv
12
- import os
13
- import re
14
- import datetime
15
- import datetime
16
-
17
- # Load environment variables
18
- load_dotenv()
19
- GOOGLE_API_KEY = os.getenv("GOOGLE_API_KEY")
20
-
21
-
22
- app = FastAPI(
23
- title="PreBot College Counselor API",
24
- description="AI-powered college counseling system with multi-agent architecture",
25
- version="1.0.0",
26
- docs_url="/docs",
27
- redoc_url="/redoc"
28
- )
29
-
30
- # Enable CORS for all origins (adjust for production)
31
- app.add_middleware(
32
- CORSMiddleware,
33
- allow_origins=["*"],
34
- allow_credentials=True,
35
- allow_methods=["*"],
36
- allow_headers=["*"],
37
- )
38
-
39
- # Use a shared session service instance
40
- session_service = InMemorySessionService()
41
-
42
- class ChatRequest(BaseModel):
43
- user_id: str
44
- session_id: str
45
- question: str
46
-
47
- class ChatResponse(BaseModel):
48
- session_id: str
49
- answer: str
50
-
51
- def preprocess_query(query: str) -> str:
52
- sorted_institutes = sorted(INSTITUTE_MAPPING.keys(), key=len, reverse=True)
53
- for key in sorted_institutes:
54
- pattern = rf'\b{re.escape(key)}\b'
55
- query = re.sub(pattern, INSTITUTE_MAPPING[key][0], query, flags=re.IGNORECASE)
56
-
57
- for key, full_name in BRANCH_MAPPING.items():
58
- pattern = rf'\b{re.escape(key)}\b'
59
- query = re.sub(pattern, full_name, query, flags=re.IGNORECASE)
60
-
61
- return query
62
-
63
- @app.options("/chat")
64
- async def chat_options():
65
- return JSONResponse(
66
- content={"message": "OK"},
67
- headers={
68
- "Access-Control-Allow-Origin": "*",
69
- "Access-Control-Allow-Methods": "POST, OPTIONS",
70
- "Access-Control-Allow-Headers": "*",
71
- }
72
- )
73
-
74
- @app.post("/chat", response_model=ChatResponse)
75
- async def chat_endpoint(req: ChatRequest):
76
- try:
77
- print(f"Received request - User ID: {req.user_id}, Session ID: {req.session_id}")
78
- print(f"Question: {req.question}")
79
-
80
- # Check if session exists, create if not (methods are NOT async for InMemorySessionService)
81
- print("Checking for existing session...")
82
- existing_session = session_service.get_session(
83
- app_name="coordinator_agent",
84
- user_id=req.user_id,
85
- session_id=req.session_id
86
- )
87
-
88
- if not existing_session:
89
- print("Creating new session...")
90
- session_service.create_session(
91
- app_name="coordinator_agent",
92
- user_id=req.user_id,
93
- session_id=req.session_id
94
- )
95
- else:
96
- print("Using existing session")
97
-
98
- # Use the shared session service for the Runner
99
- print("Creating runner...")
100
- runner = Runner(
101
- agent=coordinator,
102
- app_name="coordinator_agent",
103
- session_service=session_service # Use the shared session service
104
- )
105
-
106
- # Create properly formatted message using Google ADK types
107
- print("Processing query...")
108
- processed_query = preprocess_query(req.question)
109
- print(f"Processed query: {processed_query}")
110
-
111
- user_msg = types.Content(role="user", parts=[types.Part(text=processed_query)])
112
-
113
- print("Running agent...")
114
- agent_response = runner.run(
115
- user_id=req.user_id,
116
- session_id=req.session_id,
117
- new_message=user_msg,
118
- )
119
-
120
- # Process the generator response to extract the final answer
121
- print(f"Agent response type: {type(agent_response)}")
122
- reply_text = ""
123
-
124
- if hasattr(agent_response, '__iter__') and not isinstance(agent_response, str):
125
- print("Processing iterable response...")
126
- for event in agent_response:
127
- print(f"Processing event: {event}")
128
- if hasattr(event, 'is_final_response') and event.is_final_response():
129
- if hasattr(event, 'content') and hasattr(event.content, 'parts'):
130
- for part in event.content.parts:
131
- if hasattr(part, 'text') and part.text:
132
- reply_text = part.text
133
- break
134
- if reply_text:
135
- break
136
- elif hasattr(event, 'text'):
137
- reply_text = event.text
138
- break
139
-
140
- if not reply_text:
141
- reply_text = "Sorry, there is an issue in our end :("
142
- else:
143
- print("Processing direct response...")
144
- reply_text = str(agent_response)
145
-
146
- print(f"Final reply: {reply_text}")
147
- return ChatResponse(session_id=req.session_id, answer=reply_text)
148
- except Exception as e:
149
- print(f"Error occurred: {str(e)}")
150
- print(f"Error type: {type(e)}")
151
- import traceback
152
- print(f"Full traceback: {traceback.format_exc()}")
153
- raise HTTPException(status_code=500, detail=f"Internal server error: {str(e)}")
154
-
155
- # Add health check endpoint
156
- @app.get("/")
157
- async def root():
158
- return {
159
- "message": "PreBot College Counselor API is running!",
160
- "status": "healthy",
161
- "version": "1.0.0",
162
- "endpoints": {
163
- "chat": "/chat",
164
- "docs": "/docs",
165
- "redoc": "/redoc"
166
- }
167
- }
168
-
169
- @app.get("/health")
170
- async def health_check():
171
- return {"status": "healthy", "timestamp": datetime.datetime.now().isoformat()}
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from fastapi import FastAPI, HTTPException
2
+ from fastapi.middleware.cors import CORSMiddleware
3
+ from fastapi.responses import JSONResponse
4
+ from pydantic import BaseModel
5
+ from agents import coordinator
6
+ from google.adk.sessions import InMemorySessionService
7
+ from constants import INSTITUTE_MAPPING, BRANCH_MAPPING
8
+ from google.adk.tools import google_search
9
+ from google.adk.runners import Runner
10
+ from google.genai import types # Add this import for Content and Part
11
+ from dotenv import load_dotenv
12
+ import os
13
+ import re
14
+ import datetime
15
+
16
+ # Load environment variables
17
+ load_dotenv()
18
+ GOOGLE_API_KEY = os.getenv("GOOGLE_API_KEY")
19
+
20
+
21
+ app = FastAPI(
22
+ title="PreBot College Counselor API",
23
+ description="AI-powered college counseling system with multi-agent architecture",
24
+ version="1.0.0",
25
+ docs_url="/docs",
26
+ redoc_url="/redoc"
27
+ )
28
+
29
+ # Enable CORS for all origins (adjust for production)
30
+ app.add_middleware(
31
+ CORSMiddleware,
32
+ allow_origins=["*"],
33
+ allow_credentials=True,
34
+ allow_methods=["*"],
35
+ allow_headers=["*"],
36
+ )
37
+
38
+ # Use a shared session service instance
39
+ session_service = InMemorySessionService()
40
+
41
+ class ChatRequest(BaseModel):
42
+ user_id: str
43
+ session_id: str
44
+ question: str
45
+
46
+ class ChatResponse(BaseModel):
47
+ session_id: str
48
+ answer: str
49
+
50
+ def preprocess_query(query: str) -> str:
51
+ sorted_institutes = sorted(INSTITUTE_MAPPING.keys(), key=len, reverse=True)
52
+ for key in sorted_institutes:
53
+ pattern = rf'\b{re.escape(key)}\b'
54
+ query = re.sub(pattern, INSTITUTE_MAPPING[key][0], query, flags=re.IGNORECASE)
55
+
56
+ for key, full_name in BRANCH_MAPPING.items():
57
+ pattern = rf'\b{re.escape(key)}\b'
58
+ query = re.sub(pattern, full_name, query, flags=re.IGNORECASE)
59
+
60
+ return query
61
+
62
+ @app.options("/chat")
63
+ async def chat_options():
64
+ return JSONResponse(
65
+ content={"message": "OK"},
66
+ headers={
67
+ "Access-Control-Allow-Origin": "*",
68
+ "Access-Control-Allow-Methods": "POST, OPTIONS",
69
+ "Access-Control-Allow-Headers": "*",
70
+ }
71
+ )
72
+
73
+ @app.post("/chat", response_model=ChatResponse)
74
+ async def chat_endpoint(req: ChatRequest):
75
+ try:
76
+ print(f"Received request - User ID: {req.user_id}, Session ID: {req.session_id}")
77
+ print(f"Question: {req.question}")
78
+
79
+ # Check if session exists, create if not (methods are NOT async for InMemorySessionService)
80
+ print("Checking for existing session...")
81
+ try:
82
+ existing_session = await session_service.get_session(
83
+ app_name="coordinator_agent",
84
+ user_id=req.user_id,
85
+ session_id=req.session_id
86
+ )
87
+ except:
88
+ existing_session = None
89
+
90
+ if not existing_session:
91
+ print("Creating new session...")
92
+ try:
93
+ await session_service.create_session(
94
+ app_name="coordinator_agent",
95
+ user_id=req.user_id,
96
+ session_id=req.session_id
97
+ )
98
+ except Exception as session_error:
99
+ print(f"Session creation error: {session_error}")
100
+ else:
101
+ print("Using existing session")
102
+
103
+ # Use the shared session service for the Runner
104
+ print("Creating runner...")
105
+ runner = Runner(
106
+ agent=coordinator,
107
+ app_name="coordinator_agent",
108
+ session_service=session_service # Use the shared session service
109
+ )
110
+
111
+ # Create properly formatted message using Google ADK types
112
+ print("Processing query...")
113
+ processed_query = preprocess_query(req.question)
114
+ print(f"Processed query: {processed_query}")
115
+
116
+ user_msg = types.Content(role="user", parts=[types.Part(text=processed_query)])
117
+
118
+ print("Running agent...")
119
+ agent_response = runner.run(
120
+ user_id=req.user_id,
121
+ session_id=req.session_id,
122
+ new_message=user_msg,
123
+ )
124
+
125
+ # Process the generator response to extract the final answer
126
+ print(f"Agent response type: {type(agent_response)}")
127
+ reply_text = ""
128
+
129
+ if hasattr(agent_response, '__iter__') and not isinstance(agent_response, str):
130
+ print("Processing iterable response...")
131
+ for event in agent_response:
132
+ print(f"Processing event: {event}")
133
+
134
+ # Try multiple ways to extract text from event
135
+ if hasattr(event, 'is_final_response') and event.is_final_response():
136
+ if hasattr(event, 'content') and hasattr(event.content, 'parts'):
137
+ for part in event.content.parts:
138
+ if hasattr(part, 'text') and part.text:
139
+ reply_text = part.text
140
+ break
141
+ if reply_text:
142
+ break
143
+ elif hasattr(event, 'text'):
144
+ reply_text = event.text
145
+ break
146
+
147
+ # Also try to get content from any event that has text
148
+ if hasattr(event, 'content'):
149
+ if hasattr(event.content, 'parts'):
150
+ for part in event.content.parts:
151
+ if hasattr(part, 'text') and part.text:
152
+ reply_text += part.text + " "
153
+ elif hasattr(event.content, 'text'):
154
+ reply_text += event.content.text + " "
155
+ elif hasattr(event, 'text'):
156
+ reply_text += event.text + " "
157
+
158
+ reply_text = reply_text.strip()
159
+ if not reply_text:
160
+ reply_text = "Sorry, there is an issue in our end :("
161
+ else:
162
+ print("Processing direct response...")
163
+ reply_text = str(agent_response)
164
+
165
+ print(f"Final reply: {reply_text}")
166
+ return ChatResponse(session_id=req.session_id, answer=reply_text)
167
+ except Exception as e:
168
+ print(f"Error occurred: {str(e)}")
169
+ print(f"Error type: {type(e)}")
170
+ import traceback
171
+ print(f"Full traceback: {traceback.format_exc()}")
172
+ raise HTTPException(status_code=500, detail=f"Internal server error: {str(e)}")
173
+
174
+ # Add health check endpoint
175
+ @app.get("/")
176
+ async def root():
177
+ return {
178
+ "message": "PreBot College Counselor API is running!",
179
+ "status": "healthy",
180
+ "version": "1.0.0",
181
+ "endpoints": {
182
+ "chat": "/chat",
183
+ "docs": "/docs",
184
+ "redoc": "/redoc"
185
+ }
186
+ }
187
+
188
+ @app.get("/health")
189
+ async def health_check():
190
+ return {"status": "healthy", "timestamp": datetime.datetime.now().isoformat()}