Spaces:
Sleeping
Sleeping
Update app.py
Browse files
app.py
CHANGED
@@ -226,7 +226,7 @@
|
|
226 |
import os
|
227 |
import time
|
228 |
import requests
|
229 |
-
from fastapi import FastAPI, Request
|
230 |
from fastapi.responses import HTMLResponse, JSONResponse
|
231 |
from fastapi.staticfiles import StaticFiles
|
232 |
from pydantic import BaseModel
|
@@ -236,6 +236,11 @@ from simple_salesforce import Salesforce, SalesforceLogin
|
|
236 |
import uuid
|
237 |
import datetime
|
238 |
import json
|
|
|
|
|
|
|
|
|
|
|
239 |
|
240 |
# Define Pydantic model for incoming request body
|
241 |
class MessageRequest(BaseModel):
|
@@ -244,10 +249,10 @@ class MessageRequest(BaseModel):
|
|
244 |
# Initialize FastAPI app
|
245 |
app = FastAPI()
|
246 |
|
247 |
-
# Allow CORS requests from any domain
|
248 |
app.add_middleware(
|
249 |
CORSMiddleware,
|
250 |
-
allow_origins=["*"],
|
251 |
allow_credentials=True,
|
252 |
allow_methods=["*"],
|
253 |
allow_headers=["*"],
|
@@ -257,32 +262,49 @@ app.add_middleware(
|
|
257 |
app.mount("/static", StaticFiles(directory="static"), name="static")
|
258 |
templates = Jinja2Templates(directory="static")
|
259 |
|
260 |
-
#
|
261 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
262 |
CHATGROQ_API_KEY = os.getenv("CHATGROQ_API_KEY")
|
|
|
263 |
|
264 |
# Salesforce credentials
|
265 |
username = os.getenv("username")
|
266 |
password = os.getenv("password")
|
267 |
security_token = os.getenv("security_token")
|
268 |
-
domain = os.getenv("domain") #
|
269 |
-
|
270 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
271 |
|
272 |
# Chat history
|
273 |
chat_history = []
|
274 |
current_chat_history = []
|
|
|
275 |
|
276 |
def handle_query(query):
|
277 |
# Prepare context from chat history
|
278 |
context_str = ""
|
279 |
-
for past_query, response in reversed(current_chat_history):
|
280 |
if past_query.strip():
|
281 |
context_str += f"User asked: '{past_query}'\nBot answered: '{response}'\n"
|
282 |
|
283 |
-
# Construct the prompt
|
284 |
prompt = f"""
|
285 |
-
You are the Clara Redfernstech chatbot.
|
286 |
|
287 |
Context:
|
288 |
{context_str}
|
@@ -297,21 +319,24 @@ def handle_query(query):
|
|
297 |
"Content-Type": "application/json",
|
298 |
}
|
299 |
payload = {
|
300 |
-
"model":
|
301 |
"messages": [{"role": "user", "content": prompt}],
|
302 |
-
"max_tokens": 50,
|
303 |
"temperature": 0.1,
|
304 |
}
|
305 |
|
306 |
try:
|
307 |
-
response = requests.post(CHATGROQ_API_URL, headers=headers, json=payload)
|
|
|
308 |
response_data = response.json()
|
309 |
response_text = response_data["choices"][0]["message"]["content"].strip()
|
310 |
-
except
|
311 |
-
|
312 |
response_text = "Sorry, I couldn't find an answer."
|
313 |
|
314 |
# Update chat history
|
|
|
|
|
315 |
current_chat_history.append((query, response_text))
|
316 |
return response_text
|
317 |
|
@@ -322,35 +347,48 @@ async def load_chat(request: Request, id: str):
|
|
322 |
@app.post("/hist/")
|
323 |
async def save_chat_history(history: dict):
|
324 |
user_id = history.get('userId')
|
325 |
-
if user_id
|
326 |
-
|
|
|
327 |
|
328 |
hist = ''.join([f"'{entry['sender']}: {entry['message']}'\n" for entry in history['history']])
|
329 |
-
hist = "You are a Redfernstech summarize model.
|
330 |
|
331 |
try:
|
332 |
sf.Lead.update(user_id, {'Description': hist})
|
|
|
333 |
except Exception as e:
|
334 |
-
|
|
|
335 |
|
336 |
return {"summary": hist, "message": "Chat history saved"}
|
337 |
|
338 |
@app.post("/webhook")
|
339 |
async def receive_form_data(request: Request):
|
340 |
-
|
341 |
-
|
|
|
|
|
|
|
|
|
|
|
342 |
data = {
|
343 |
'FirstName': first_name,
|
344 |
'LastName': last_name,
|
345 |
'Description': 'hii', # Static description
|
346 |
-
'Company': form_data
|
347 |
-
'Phone': form_data
|
348 |
-
'Email': form_data
|
349 |
}
|
350 |
-
|
351 |
-
|
352 |
-
|
353 |
-
|
|
|
|
|
|
|
|
|
|
|
354 |
|
355 |
@app.post("/chat/")
|
356 |
async def chat(request: MessageRequest):
|
@@ -362,7 +400,10 @@ async def chat(request: MessageRequest):
|
|
362 |
"response": response,
|
363 |
"timestamp": datetime.datetime.now().isoformat()
|
364 |
}
|
|
|
|
|
365 |
chat_history.append(message_data)
|
|
|
366 |
return {"response": response}
|
367 |
|
368 |
@app.get("/")
|
@@ -372,12 +413,8 @@ def read_root():
|
|
372 |
def split_name(full_name):
|
373 |
words = full_name.strip().split()
|
374 |
if len(words) == 1:
|
375 |
-
|
376 |
-
last_name = words[0]
|
377 |
elif len(words) == 2:
|
378 |
-
|
379 |
-
last_name = words[1]
|
380 |
else:
|
381 |
-
|
382 |
-
last_name = ' '.join(words[1:])
|
383 |
-
return first_name, last_name
|
|
|
226 |
import os
|
227 |
import time
|
228 |
import requests
|
229 |
+
from fastapi import FastAPI, Request, HTTPException
|
230 |
from fastapi.responses import HTMLResponse, JSONResponse
|
231 |
from fastapi.staticfiles import StaticFiles
|
232 |
from pydantic import BaseModel
|
|
|
236 |
import uuid
|
237 |
import datetime
|
238 |
import json
|
239 |
+
import logging
|
240 |
+
|
241 |
+
# Configure logging
|
242 |
+
logging.basicConfig(level=logging.INFO)
|
243 |
+
logger = logging.getLogger(__name__)
|
244 |
|
245 |
# Define Pydantic model for incoming request body
|
246 |
class MessageRequest(BaseModel):
|
|
|
249 |
# Initialize FastAPI app
|
250 |
app = FastAPI()
|
251 |
|
252 |
+
# Allow CORS requests from any domain (not recommended for production)
|
253 |
app.add_middleware(
|
254 |
CORSMiddleware,
|
255 |
+
allow_origins=["*"], # Allows all origins
|
256 |
allow_credentials=True,
|
257 |
allow_methods=["*"],
|
258 |
allow_headers=["*"],
|
|
|
262 |
app.mount("/static", StaticFiles(directory="static"), name="static")
|
263 |
templates = Jinja2Templates(directory="static")
|
264 |
|
265 |
+
# Validate environment variables
|
266 |
+
required_env_vars = ["CHATGROQ_API_KEY", "username", "password", "security_token", "domain"]
|
267 |
+
for var in required_env_vars:
|
268 |
+
if not os.getenv(var):
|
269 |
+
logger.error(f"Environment variable {var} is not set")
|
270 |
+
raise ValueError(f"Environment variable {var} is not set")
|
271 |
+
|
272 |
+
# Configure ChatGroq API (replace with actual endpoint and model)
|
273 |
+
CHATGROQ_API_URL = os.getenv("CHATGROQ_API_URL", "https://api.example.com/v1/chat/completions") # Update with correct endpoint
|
274 |
CHATGROQ_API_KEY = os.getenv("CHATGROQ_API_KEY")
|
275 |
+
CHATGROQ_MODEL = os.getenv("CHATGROQ_MODEL", "default-model") # Update with correct model
|
276 |
|
277 |
# Salesforce credentials
|
278 |
username = os.getenv("username")
|
279 |
password = os.getenv("password")
|
280 |
security_token = os.getenv("security_token")
|
281 |
+
domain = os.getenv("domain") # e.g., 'test' for sandbox
|
282 |
+
|
283 |
+
# Initialize Salesforce connection
|
284 |
+
try:
|
285 |
+
session_id, sf_instance = SalesforceLogin(
|
286 |
+
username=username, password=password, security_token=security_token, domain=domain
|
287 |
+
)
|
288 |
+
sf = Salesforce(instance=sf_instance, session_id=session_id)
|
289 |
+
except Exception as e:
|
290 |
+
logger.error(f"Failed to connect to Salesforce: {e}")
|
291 |
+
raise HTTPException(status_code=500, detail="Salesforce connection failed")
|
292 |
|
293 |
# Chat history
|
294 |
chat_history = []
|
295 |
current_chat_history = []
|
296 |
+
MAX_HISTORY_SIZE = 100 # Limit chat history size
|
297 |
|
298 |
def handle_query(query):
|
299 |
# Prepare context from chat history
|
300 |
context_str = ""
|
301 |
+
for past_query, response in reversed(current_chat_history[-10:]): # Limit context to last 10 exchanges
|
302 |
if past_query.strip():
|
303 |
context_str += f"User asked: '{past_query}'\nBot answered: '{response}'\n"
|
304 |
|
305 |
+
# Construct the prompt
|
306 |
prompt = f"""
|
307 |
+
You are the Clara Redfernstech chatbot. Provide accurate, professional answers in 10-15 words.
|
308 |
|
309 |
Context:
|
310 |
{context_str}
|
|
|
319 |
"Content-Type": "application/json",
|
320 |
}
|
321 |
payload = {
|
322 |
+
"model": CHATGROQ_MODEL, # Use configured model
|
323 |
"messages": [{"role": "user", "content": prompt}],
|
324 |
+
"max_tokens": 50,
|
325 |
"temperature": 0.1,
|
326 |
}
|
327 |
|
328 |
try:
|
329 |
+
response = requests.post(CHATGROQ_API_URL, headers=headers, json=payload, timeout=10)
|
330 |
+
response.raise_for_status() # Raise exception for bad status codes
|
331 |
response_data = response.json()
|
332 |
response_text = response_data["choices"][0]["message"]["content"].strip()
|
333 |
+
except requests.exceptions.RequestException as e:
|
334 |
+
logger.error(f"Error querying ChatGroq API: {e}")
|
335 |
response_text = "Sorry, I couldn't find an answer."
|
336 |
|
337 |
# Update chat history
|
338 |
+
if len(current_chat_history) >= MAX_HISTORY_SIZE:
|
339 |
+
current_chat_history.pop(0) # Remove oldest entry
|
340 |
current_chat_history.append((query, response_text))
|
341 |
return response_text
|
342 |
|
|
|
347 |
@app.post("/hist/")
|
348 |
async def save_chat_history(history: dict):
|
349 |
user_id = history.get('userId')
|
350 |
+
if not user_id:
|
351 |
+
logger.error("userId is missing in history request")
|
352 |
+
raise HTTPException(status_code=400, detail="userId is required")
|
353 |
|
354 |
hist = ''.join([f"'{entry['sender']}: {entry['message']}'\n" for entry in history['history']])
|
355 |
+
hist = "You are a Redfernstech summarize model. Identify user interests from this conversation: " + hist
|
356 |
|
357 |
try:
|
358 |
sf.Lead.update(user_id, {'Description': hist})
|
359 |
+
logger.info(f"Chat history updated for user {user_id}")
|
360 |
except Exception as e:
|
361 |
+
logger.error(f"Failed to update lead: {e}")
|
362 |
+
raise HTTPException(status_code=500, detail=f"Failed to update lead: {str(e)}")
|
363 |
|
364 |
return {"summary": hist, "message": "Chat history saved"}
|
365 |
|
366 |
@app.post("/webhook")
|
367 |
async def receive_form_data(request: Request):
|
368 |
+
try:
|
369 |
+
form_data = await request.json()
|
370 |
+
except json.JSONDecodeError:
|
371 |
+
logger.error("Invalid JSON in webhook request")
|
372 |
+
raise HTTPException(status_code=400, detail="Invalid JSON")
|
373 |
+
|
374 |
+
first_name, last_name = split_name(form_data.get('name', ''))
|
375 |
data = {
|
376 |
'FirstName': first_name,
|
377 |
'LastName': last_name,
|
378 |
'Description': 'hii', # Static description
|
379 |
+
'Company': form_data.get('company', ''),
|
380 |
+
'Phone': form_data.get('phone', '').strip(),
|
381 |
+
'Email': form_data.get('email', ''),
|
382 |
}
|
383 |
+
|
384 |
+
try:
|
385 |
+
result = sf.Lead.create(data)
|
386 |
+
unique_id = result['id']
|
387 |
+
logger.info(f"Lead created with ID {unique_id}")
|
388 |
+
return JSONResponse({"id": unique_id})
|
389 |
+
except Exception as e:
|
390 |
+
logger.error(f"Failed to create lead: {e}")
|
391 |
+
raise HTTPException(status_code=500, detail="Failed to create lead: {str(e)}")
|
392 |
|
393 |
@app.post("/chat/")
|
394 |
async def chat(request: MessageRequest):
|
|
|
400 |
"response": response,
|
401 |
"timestamp": datetime.datetime.now().isoformat()
|
402 |
}
|
403 |
+
if len(chat_history) >= MAX_HISTORY_SIZE:
|
404 |
+
chat_history.pop(0) # Remove oldest entry
|
405 |
chat_history.append(message_data)
|
406 |
+
logger.info(f"Chat message processed: {message}")
|
407 |
return {"response": response}
|
408 |
|
409 |
@app.get("/")
|
|
|
413 |
def split_name(full_name):
|
414 |
words = full_name.strip().split()
|
415 |
if len(words) == 1:
|
416 |
+
return '', words[0]
|
|
|
417 |
elif len(words) == 2:
|
418 |
+
return words[0], words[1]
|
|
|
419 |
else:
|
420 |
+
return words[0], ' '.join(words[1:])
|
|
|
|