Spaces:
Sleeping
Sleeping
File size: 6,104 Bytes
c6360d9 | 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 |
import gradio as gr
import os
from openai import OpenAI
from pydantic import BaseModel
from PyPDF2 import PdfReader
# --- Configuration and API Key Setup ---
openai_api_key = os.environ.get('OPENAI_API_KEY')
google_api_key = os.environ.get('GOOGLE_API_KEY')
if not openai_api_key:
raise ValueError("OPENAI_API_KEY not found in environment variables. Please set it as a Space Secret.")
if not google_api_key:
raise ValueError("GOOGLE_API_KEY not found in environment variables. Please set it as a Space Secret.")
openai_client_deployed = OpenAI(api_key=openai_api_key)
gemini_client_deployed = OpenAI(api_key=google_api_key, base_url="https://generativelanguage.googleapis.com/v1beta/openai/")
# --- Data Loading (for deployment) ---
name = "Ed Donner"
try:
reader = PdfReader("linkedin.pdf")
linkedin = ""
for page in reader.pages:
text = page.extract_text()
if text:
linkedin += text
except Exception as e:
print(f"Could not load linkedin.pdf in deployed app: {e}. Using placeholder.")
linkedin = "LinkedIn profile content could not be loaded. Please ensure linkedin.pdf is in your Space."
try:
with open("summary.txt", "r", encoding="utf-8") as f:
summary = f.read()
except Exception as e:
print(f"Could not load summary.txt in deployed app: {e}. Using placeholder.")
summary = "Summary content could not be loaded. Please ensure summary.txt is in your Space."
# --- System Prompts and Pydantic Model ---
system_prompt = f"""You are acting as {name}. You are answering questions on {name}'s website, \
particularly questions related to {name}'s career, background, skills and experience. \
Your responsibility is to represent {name} for interactions on the website as faithfully as possible. \
You are given a summary of {name}'s background and LinkedIn profile which you can use to answer questions. \
Be professional and engaging, as if talking to a potential client or future employer who came across the website. \
If you don't know the answer, say so."""
system_prompt += f"""\n\n## Summary:\n{summary}\n\n## LinkedIn Profile:\n{linkedin}\n\n"""
system_prompt += f"""With this context, please chat with the user, always staying in character as {name}."""
class Evaluation(BaseModel):
is_acceptable: bool
feedback: str
evaluator_system_prompt = f"""You are an evaluator that decides whether a response to a question is acceptable. \
You are provided with a conversation between a User and an Agent. Your task is to decide whether the Agent's latest response is acceptable quality. \
The Agent is playing the role of {name} and is representing {name} on their website. \
The Agent has been instructed to be professional and engaging, as if talking to a potential client or future employer who came across the website. \
The Agent has been provided with context on {name} in the form of their summary and LinkedIn details. Here's the information:"""
evaluator_system_prompt += f"""\n\n## Summary:\n{summary}\n\n## LinkedIn Profile:\n{linkedin}\n\n"""
evaluator_system_prompt += f"""With this context, please evaluate the latest response, replying with whether the response is acceptable and your feedback."""
def evaluator_user_prompt(reply, message, history):
user_prompt = f"""Here's the conversation between the User and the Agent: \n\n{history}\n\n"""
user_prompt += f"""Here's the latest message from the User: \n\n{message}\n\n"""
user_prompt += f"""Here's the latest response from the Agent: \n\n{reply}\n\n"""
user_prompt += f"""Please evaluate the response, replying with whether it is acceptable and your feedback."""
return user_prompt
def evaluate(reply, message, history) -> Evaluation:
messages = [{"role": "system", "content": evaluator_system_prompt}] + [{"role": "user", "content": evaluator_user_prompt(reply, message, history)}]
response = gemini_client_deployed.beta.chat.completions.parse(model="gemini-2.0-flash", messages=messages, response_format=Evaluation)
return response.choices[0].message.parsed
def rerun(reply, message, history, feedback):
updated_system_prompt = system_prompt + f"""\n\n## Previous answer rejected\nYou just tried to reply, but the quality control rejected your reply\n"""
updated_system_prompt += f"""## Your attempted answer:\n{reply}\n\n"""
updated_system_prompt += f"""## Reason for rejection:\n{feedback}\n\n"""
messages = [{"role": "system", "content": updated_system_prompt}] + history + [{"role": "user", "content": message}]
response = openai_client_deployed.chat.completions.create(model="gpt-4o-mini", messages=messages)
return response.choices[0].message.content
# --- Main Chat Function for Gradio ---
def chat(message, history):
if "patent" in message:
system = system_prompt + "\n\nEverything in your reply needs to be in pig latin - \
it is mandatory that you respond only and entirely in pig latin"
else:
system = system_prompt
messages = [{"role": "system", "content": system}] + history + [{"role": "user", "content": message}]
response = openai_client_deployed.chat.completions.create(model="gpt-4o-mini", messages=messages)
reply = response.choices[0].message.content
# Evaluation logic
evaluation = evaluate(reply, message, history)
if evaluation.is_acceptable:
print("Passed evaluation - returning reply")
else:
print("Failed evaluation - retrying")
print(evaluation.feedback)
reply = rerun(reply, message, history, evaluation.feedback)
return reply
# --- Gradio Interface (for Hugging Face Spaces) ---
# Define the Gradio interface
demo = gr.ChatInterface(chat, type="messages")
# This is the line that Hugging Face Spaces looks for to run your app.
# It does NOT need a .launch() call here when deployed to HF Spaces, as the Space environment handles that.
# However, for `gradio deploy` to infer the SDK, this `demo` object definition is key.
# The `if __name__ == "__main__":` block is for local Colab testing only.
if __name__ == "__main__":
demo.launch()
|