File size: 5,745 Bytes
0af0679 |
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 |
import os
import json
from openai import OpenAI
from dotenv import load_dotenv
from tools import _record_user_details
load_dotenv(override=True)
OPENAI_API_KEY = os.getenv("OPENAI_API_KEY")
MODEL = "gpt-4o-mini-2024-07-18"
NAME = "Damla"
# Tool: Record user interest
record_user_details_json = {
"name": "record_user_details",
"description": "Use this tool to record that a user provided an email address and they are interested in being in touch and provided an email address",
"parameters": {
"type": "object",
"properties": {
"email": {
"type": "string",
"description": "The email address of this user. Format should be similar to this: [email protected]"
},
"name": {
"type": "string",
"description": "The user's name, if they provided it"
},
"notes": {
"type": "string",
"description": "Any additional information about the conversation that's worth recording to give context"
}
},
"required": ["email"],
"additionalProperties": False
}
}
TOOL_FUNCTIONS = {
"record_user_details": _record_user_details,
}
TOOLS = [{"type": "function", "function": record_user_details_json}]
class Chat:
def __init__(self, name=NAME, model=MODEL, tools=TOOLS):
self.name = name
self.model = model
self.tools = tools
self.client = OpenAI()
def _get_system_prompt(self):
return (f"""
You are acting as {self.name}. You are answering questions on {self.name}'s website, particularly questions related to {self.name}'s career, background, skills, and experience.
You are given a summary of {self.name}'s background and LinkedIn profile which you should use as the only source of truth to answer questions.
Interpret and answer based strictly on the information provided.
You should never generate or write code. If asked to write code or build an app, explain whether {self.name}'s experience or past projects are relevant to the task,
and what approach {self.name} would take. If {self.name} has no relevant experience, politely acknowledge that.
If a project is mentioned, specify whether it's a personal project or a professional one. Be professional and engaging —
the tone should be warm, clear, and appropriate for a potential client or future employer.
If a visitor engages in a discussion, try to steer them towards getting in touch via email. Ask for their email and record it using your record_user_details tool.
Only accept inputs that follow the standard email format (like [email protected]). Do not confuse emails with phone numbers or usernames. If in doubt, ask for clarification.
If you don't know the answer, just say so.
"""
)
def _handle_tool_calls(self, tool_calls, recorded_emails):
results = []
for call in tool_calls:
tool_name = call.function.name
arguments = json.loads(call.function.arguments)
if arguments["email"] in recorded_emails:
result = {"recorded": "ok"}
results.append({
"role": "tool",
"content": json.dumps(result),
"tool_call_id": call.id
})
continue
print(f"Tool called: {tool_name}")
func = TOOL_FUNCTIONS.get(tool_name)
if func:
result = func(**arguments)
results.append({
"role": "tool",
"content": json.dumps(result),
"tool_call_id": call.id
})
recorded_emails.add(arguments["email"])
return results
def chat(self, message, history, recorded_emails=set(), retrieved_chunks=None):
if retrieved_chunks:
message += f"\n\nUse the following context if helpful:\n{retrieved_chunks}"
messages = [{"role": "system", "content": self._get_system_prompt()}] + history + [{"role": "user", "content": message}]
done = False
while not done:
response = self.client.chat.completions.create(
model=self.model,
messages=messages,
tools=self.tools,
max_tokens=400,
temperature=0.5
)
finish_reason = response.choices[0].finish_reason
if finish_reason == "tool_calls":
message_obj = response.choices[0].message
tool_calls = message_obj.tool_calls
results = self._handle_tool_calls(tool_calls, recorded_emails)
messages.append(message_obj)
messages.extend(results)
else:
done = True
return response.choices[0].message.content, recorded_emails
def rerun(self, original_reply, message, history, feedback):
updated_prompt = self._get_system_prompt()
updated_prompt += (
"\n\n## Previous answer rejected\nYou just tried to reply, but the quality control rejected your reply.\n"
f"## Your attempted answer:\n{original_reply}\n\n"
f"## Reason for rejection:\n{feedback}\n"
)
messages = [{"role": "system", "content": updated_prompt}] + history + [{"role": "user", "content": message}]
response = self.client.chat.completions.create(model=self.model, messages=messages)
return response.choices[0].message.content
|