File size: 4,877 Bytes
97f4e58
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
from dotenv import load_dotenv
from openai import OpenAI
import json
import os
import requests
from pypdf import PdfReader
import gradio as gr

load_dotenv(override=True)

def push(text):
    requests.post(
        "https://api.pushover.net/1/messages.json",
        data={
            "token": os.getenv("PUSHOVER_TOKEN"),
            "user": os.getenv("PUSHOVER_USER"),
            "message": text,
        }
    )

def record_user_details(email, name="Name not provided", notes="not provided"):
    push(f"Recording {name} with email {email} and notes {notes}")
    return {"recorded": "ok"}

def record_unknown_question(question):
    push(f"Recording unknown question: {question}")
    return {"recorded": "ok"}

record_user_details_json = {
    "name": "record_user_details",
    "description": "Use this tool to record that a user is interested in being in touch and provided an email address",
    "parameters": {
        "type": "object",
        "properties": {
            "email": {"type": "string", "description": "The email address of this user"},
            "name": {"type": "string", "description": "The user's name, if they provided it"},
            "notes": {"type": "string", "description": "Any additional context"},
        },
        "required": ["email"],
        "additionalProperties": False
    }
}

record_unknown_question_json = {
    "name": "record_unknown_question",
    "description": "Record any question that couldn't be answered",
    "parameters": {
        "type": "object",
        "properties": {
            "question": {"type": "string", "description": "The question that couldn't be answered"},
        },
        "required": ["question"],
        "additionalProperties": False
    }
}

tools = [
    {"type": "function", "function": record_user_details_json},
    {"type": "function", "function": record_unknown_question_json}
]

class JoshuaChatBot:
    def __init__(self):
        self.openai = OpenAI()
        self.name = "Joshua Sam Mathew"

        # Read resume
        reader = PdfReader("JoshuaCh/josh_resume.pdf")
        self.josh_resume = "".join(page.extract_text() or "" for page in reader.pages)

        # Read LinkedIn
        reader = PdfReader("JoshuaCh/josh_linkedin.pdf")
        self.josh_linkedin = "".join(page.extract_text() or "" for page in reader.pages)

        # Read summary
        with open("JoshuaCh/josh_summary.txt", "r", encoding="utf-8") as f:
            self.josh_summary = f.read()

    def system_prompt(self):
        return f"""

        You are acting as {self.name}. You are answering questions on {self.name}'s website,

        particularly about his career, background, skills, and experience.

        Be professional and engaging, as if speaking to a potential client or employer.

        Use the summary, resume, and LinkedIn information to answer accurately.

        If you don't know an answer, use the record_unknown_question tool. But if its a common question or basic question thats not related to my carear details u can answer it on your own keeping everything proffessional, even if it's about something trivial or unrelated to career.

        If a user wants to connect, ask for their email and record it with record_user_details.

        ## Summary:

        {self.josh_summary}

        ## Resume:

        {self.josh_resume}

        ## LinkedIn:

        {self.josh_linkedin}

        """

    def handle_tool_call(self, tool_calls):
        results = []
        for tool_call in tool_calls:
            fn = tool_call.function.name
            args = json.loads(tool_call.function.arguments)
            if fn == "record_user_details":
                result = record_user_details(**args)
            elif fn == "record_unknown_question":
                result = record_unknown_question(**args)
            else:
                result = {"error": "Unknown tool"}
            results.append({"role": "tool", "content": json.dumps(result)})
        return results

    def chat(self, message, history):
        messages = [{"role": "system", "content": self.system_prompt()}] + history + [{"role": "user", "content": message}]

        done = False
        while not done:
            response = self.openai.chat.completions.create(model="gpt-4o-mini", messages=messages, tools=tools)
            msg = response.choices[0].message

            if hasattr(msg, "tool_calls") and msg.tool_calls:
                results = self.handle_tool_call(msg.tool_calls)
                messages.append(msg)
                messages.extend(results)
            else:
                done = True

        return response.choices[0].message.content

if __name__ == "__main__":
    josh = JoshuaChatBot()
    gr.ChatInterface(josh.chat, type="messages").launch()