Spaces:
Sleeping
Sleeping
| from dotenv import load_dotenv | |
| from openai import OpenAI | |
| import json | |
| import os | |
| from pypdf import PdfReader | |
| import gradio as gr | |
| import csv | |
| # Load environment variables | |
| load_dotenv(override=True) | |
| GEMINI_BASE_URL = "https://generativelanguage.googleapis.com/v1beta/openai/" | |
| google_api_key = os.getenv("GOOGLE_API_KEY") | |
| gemini = OpenAI(base_url=GEMINI_BASE_URL, api_key=google_api_key) | |
| # CSV files for logging | |
| USER_CSV = "user_details.csv" | |
| UNKNOWN_CSV = "unknown_questions.csv" | |
| # Ensure CSV files exist with headers | |
| for file, headers in [(USER_CSV, ["email", "name", "notes"]), | |
| (UNKNOWN_CSV, ["question"])]: | |
| if not os.path.exists(file): | |
| with open(file, "w", newline="", encoding="utf-8") as f: | |
| writer = csv.writer(f) | |
| writer.writerow(headers) | |
| # Functions to log user details and unknown questions | |
| def record_user_details(email, name="Name not provided", notes="not provided"): | |
| with open(USER_CSV, "a", newline="", encoding="utf-8") as f: | |
| writer = csv.writer(f) | |
| writer.writerow([email, name, notes]) | |
| return {"recorded": "ok"} | |
| def record_unknown_question(question): | |
| with open(UNKNOWN_CSV, "a", newline="", encoding="utf-8") as f: | |
| writer = csv.writer(f) | |
| writer.writerow([question]) | |
| return {"recorded": "ok"} | |
| # JSON definitions for tools | |
| record_user_details_json = { | |
| "name": "record_user_details", | |
| "description": "Record user info when they provide email", | |
| "parameters": { | |
| "type": "object", | |
| "properties": { | |
| "email": {"type": "string", "description": "The user's email"}, | |
| "name": {"type": "string", "description": "User's name"}, | |
| "notes": {"type": "string", "description": "Extra info"} | |
| }, | |
| "required": ["email"], | |
| "additionalProperties": False | |
| } | |
| } | |
| record_unknown_question_json = { | |
| "name": "record_unknown_question", | |
| "description": "Record any unanswered question", | |
| "parameters": { | |
| "type": "object", | |
| "properties": { | |
| "question": {"type": "string", "description": "The question not answered"}, | |
| }, | |
| "required": ["question"], | |
| "additionalProperties": False | |
| } | |
| } | |
| tools = [ | |
| {"type": "function", "function": record_user_details_json}, | |
| {"type": "function", "function": record_unknown_question_json} | |
| ] | |
| class Me: | |
| def __init__(self): | |
| self.openai = gemini | |
| self.name = "SnehaLeela" | |
| # Load profile JSON | |
| with open("profile.json", "r", encoding="utf-8") as f: | |
| self.profile = json.load(f) | |
| # Set attributes for easier access | |
| self.personal_info = self.profile.get("personal_info", {}) | |
| self.expertise = self.profile.get("expertise", []) | |
| self.experience = self.profile.get("experience", []) | |
| self.education = self.profile.get("education", []) | |
| self.friends = self.profile.get("friends", []) | |
| # Handle tool calls | |
| def handle_tool_call(self, tool_calls): | |
| results = [] | |
| for tool_call in tool_calls: | |
| tool_name = tool_call.function.name | |
| arguments = json.loads(tool_call.function.arguments) | |
| tool = globals().get(tool_name) | |
| result = tool(**arguments) if tool else {} | |
| results.append({"role": "tool", "content": json.dumps(result), "tool_call_id": tool_call.id}) | |
| return results | |
| # System prompt for LLM | |
| def system_prompt(self): | |
| # Combine experience into text | |
| experience_text = "" | |
| for company in self.experience: | |
| experience_text += f"{company['company']}" | |
| if 'location' in company: | |
| experience_text += f" ({company['location']})" | |
| for role in company.get('roles', []): | |
| experience_text += f"\n- {role['title']} ({role.get('years', '')})" | |
| for hl in role.get('highlights', []): | |
| experience_text += f"\n • {hl}" | |
| experience_text += "\n" | |
| expertise_text = ", ".join(self.expertise) | |
| education_text = "" | |
| if hasattr(self, 'education') and self.education: | |
| highest = self.education[0].get("highest_degree", {}) | |
| education_text = f"{highest.get('degree','')} in {highest.get('field_of_study','')} from {highest.get('university','')} ({highest.get('start_year','')}–{highest.get('end_year','')})" | |
| # Optional: prepare friends text for fun | |
| friends_text = "" | |
| if hasattr(self, 'friends') and self.friends: | |
| friends_list = [] | |
| for f in self.friends: | |
| friends_list.append(f"{f.get('Name','')} ({f.get('Company','')}): {f.get('Description','')}") | |
| friends_text = "\n".join(friends_list) | |
| system_prompt = ( | |
| f"You are acting as {self.personal_info['name']} (aka {self.personal_info.get('nickname','')}). " | |
| f"Answer questions about {self.personal_info['name']}'s career, background, skills, and experience. " | |
| f"Represent {self.personal_info['name']} faithfully. " | |
| f"If you don't know an answer, use record_unknown_question tool. " | |
| f"If the user engages in discussion, try to steer them towards providing their email using record_user_details tool.\n\n" | |
| f"## Summary:\n{self.personal_info['summary']}\n\n" | |
| f"## Interests:\n{', '.join(self.personal_info.get('personal_interests', []))}\n\n" | |
| f"## Travel History:\n{', '.join(self.personal_info.get('travel_history', []))}\n\n" | |
| f"## Education:\n{education_text}\n\n" | |
| f"## Expertise:\n{expertise_text}\n\n" | |
| f"## Experience:\n{experience_text}\n\n" | |
| f"## Friends (for fun):\n{friends_text}\n\n" | |
| f"## LinkedIn Profile:\nhttps://www.linkedin.com/in/sneha-leela-0a450349/\n\n" | |
| f"Chat with the user staying in character as {self.personal_info['name']}." | |
| ) | |
| return system_prompt | |
| # Main chat function | |
| def chat(self, message, history): | |
| messages = [{"role": "system", "content": self.system_prompt()}] + history + [{"role": "user", "content": message}] | |
| done = False | |
| #while not done: | |
| # Send the first message | |
| response = self.openai.chat.completions.create( | |
| model="gemini-2.5-flash-preview-05-20", | |
| messages=messages, | |
| tools=tools | |
| ) | |
| # Check if the response contains tool calls | |
| if response.choices[0].finish_reason == "tool_calls": | |
| message_to_add = response.choices[0].message | |
| tool_calls_to_execute = message_to_add.tool_calls | |
| # Execute the tool and get the result. | |
| results = self.handle_tool_call(tool_calls_to_execute) | |
| # Append the tool call and its output to the messages list. | |
| messages.append(message_to_add) | |
| messages.extend(results) | |
| # Now call the API again with the tool output | |
| response = self.openai.chat.completions.create( | |
| model="gemini-2.5-flash-preview-05-20", | |
| messages=messages, | |
| ) | |
| return response.choices[0].message.content | |
| else: | |
| # If no tool call, return the direct response | |
| return response.choices[0].message.content | |
| # Custom CSS with your local image | |
| css_code = """ | |
| div { | |
| background-image: url("file/Gemini_Generated.png"); /* Your local image */ | |
| background-size: cover; | |
| background-position: center; | |
| background-repeat: no-repeat; | |
| } | |
| .gradio-container { | |
| background-color: rgba(255, 255, 255, 0.6); /* Optional overlay for readability */ | |
| } | |
| .chat-message.user { | |
| background-color: rgba(208, 230, 255, 0.8); | |
| } | |
| .chat-message.bot { | |
| background-color: rgba(224, 255, 224, 0.8); | |
| } | |
| """ | |
| # Launch Gradio interface | |
| if __name__ == "__main__": | |
| me = Me() | |
| #gr.ChatInterface(me.chat, type="messages",theme="NoCrypt/miku",).launch(share=True) | |
| gr.ChatInterface( | |
| me.chat, | |
| theme="NoCrypt/miku", | |
| title="SnehaLeela's Careerbot", | |
| #css=css_code | |
| ).launch(share=True) | |