thebendu commited on
Commit
16cc10f
·
1 Parent(s): fc15a90

OpenAI chatbot

Browse files
app.py DELETED
@@ -1,16 +0,0 @@
1
- from openai import OpenAI
2
-
3
- client = OpenAI()
4
-
5
- if __name__ == '__main__':
6
- completion = client.chat.completions.create(
7
- model="gpt-4o-mini",
8
- messages=[
9
- {"role": "system",
10
- "content":
11
- "You are a stoic assistant, skilled answers every question with a flare of philosophy on life and death."},
12
- {"role": "user", "content": "What is python and what it is used for?"}
13
- ]
14
- )
15
-
16
- print(completion.choices[0].message)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
bot.py ADDED
@@ -0,0 +1,24 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os.path
2
+ import pathlib
3
+ from pathlib import Path
4
+
5
+ from openai import OpenAI
6
+
7
+ from scripts.components import OpenAIBot
8
+ from scripts.io.terminal import TerminalIO
9
+
10
+ exit_codes = ["done", "quit", "exit"]
11
+
12
+ client = OpenAI()
13
+ prompt = pathlib.Path(__file__).parent.resolve() / "system_prompts" / "financial_bot.txt"
14
+ input_output = TerminalIO("User: ", "Agent: ")
15
+
16
+ openai_bot = OpenAIBot(client, "gpt-4o-mini", prompt, 10, input_output,
17
+ exit_codes=exit_codes)
18
+
19
+ if __name__ == '__main__':
20
+ openai_bot.start()
21
+ while openai_bot.interact():
22
+ pass
23
+
24
+
commons/__init__.py ADDED
File without changes
commons/utils.py ADDED
@@ -0,0 +1,5 @@
 
 
 
 
 
 
1
+
2
+
3
+ def getdefault(data: dict, key, default):
4
+ return default if not data.__contains__(key) else data[key]
5
+
scripts/__init__.py ADDED
File without changes
scripts/components.py ADDED
@@ -0,0 +1,100 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from enum import Enum
2
+ from os import PathLike
3
+
4
+ from openai import OpenAI
5
+
6
+ from commons.utils import getdefault
7
+ from scripts.io import InputOutput
8
+
9
+
10
+ DEFAULT_WELCOME_MESSAGE = "How can I assist you ..."
11
+ DEFAULT_USER_PROMPT = "User: "
12
+ DEFAULT_AGENT_PROMPT = "Agent: "
13
+ DEFAULT_EXIT_MESSAGE = "Have a nice day!"
14
+
15
+
16
+ class Role(Enum):
17
+ SYSTEM = "system"
18
+ USER = "user"
19
+ ASSISTANT = "assistant"
20
+
21
+
22
+ class ChatHistory:
23
+ def __init__(self, context_span: int, initial_context: list[dict[str, str]]):
24
+ self.__context_span = context_span
25
+ self.__context = list()
26
+ for context in initial_context:
27
+ self.__add_context(context)
28
+
29
+ def __ensure_max_size(self):
30
+ while len(self.__context) > self.__context_span:
31
+ self.__context.pop(1)
32
+ return self
33
+
34
+ def __add_context(self, context: dict[str, str]) -> "ChatHistory":
35
+ self.__context.append(context)
36
+ return self.__ensure_max_size()
37
+
38
+ def add_message(self, role: Role, content: str) -> "ChatHistory":
39
+ return self.__add_context({"role": role.value, "content": content})
40
+
41
+ def get_whole_context(self) -> list[dict[str, str]]:
42
+ return self.__ensure_max_size().__context.copy()
43
+
44
+ def get_chat_history(self) -> list[dict[str, str]]:
45
+ return self.get_whole_context()[0:]
46
+
47
+ def get_context_size(self) -> int:
48
+ return len(self.__ensure_max_size().__context)
49
+
50
+ def last_in_history(self):
51
+ return self.__context[-1]
52
+
53
+ def reset(self) -> "ChatHistory":
54
+ self.__context.clear()
55
+ return self
56
+
57
+
58
+ class OpenAIBot:
59
+ def __init__(self, bot: OpenAI, model: str, prompt: PathLike | str, context_span: int, io: InputOutput, **args):
60
+ self.__bot = bot
61
+ self.__model = model
62
+ final_prompt = prompt
63
+ if isinstance(prompt, PathLike):
64
+ with open(prompt, "r") as pf:
65
+ final_prompt = pf.read()
66
+ self.__history = ChatHistory(context_span=context_span,
67
+ initial_context=[{"role": Role.SYSTEM.value, "content": final_prompt}])
68
+ self.io = io
69
+
70
+ self.__welcome_message: str = getdefault(args, "welcome_message", DEFAULT_WELCOME_MESSAGE)
71
+ self.__exit_codes: list = getdefault(args, "exit_codes", list())
72
+ self.__exit_message: str = getdefault(args, "exit_message", DEFAULT_EXIT_MESSAGE)
73
+
74
+ def __is_exit(self, message: str) -> bool:
75
+ return message.lower() in self.__exit_codes
76
+
77
+ def start(self):
78
+ self.io.output(self.__welcome_message)
79
+
80
+ def interact(self) -> bool:
81
+ user_input = self.io.input()
82
+
83
+ if self.__is_exit(user_input):
84
+ self.io.output(self.__exit_message)
85
+ return False
86
+
87
+ if user_input:
88
+ messages = self.__history.add_message(Role.USER, user_input).get_whole_context()
89
+
90
+ chat = self.__bot.chat.completions.create(model=self.__model, messages=messages)
91
+ print(f"Tokens count, prompts: {chat.usage.prompt_tokens}, completion: {chat.usage.completion_tokens}, "
92
+ f"total: {chat.usage.total_tokens}")
93
+ # del messages
94
+
95
+ reply = chat.choices[0].message.content
96
+ self.io.output(reply)
97
+ self.__history.add_message(Role.ASSISTANT, reply)
98
+
99
+ return True
100
+
scripts/io/__init__.py ADDED
@@ -0,0 +1,12 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from abc import ABC, abstractmethod
2
+
3
+
4
+ class InputOutput(ABC):
5
+
6
+ @abstractmethod
7
+ def input(self) -> str:
8
+ ...
9
+
10
+ @abstractmethod
11
+ def output(self, message: str):
12
+ ...
scripts/io/terminal.py ADDED
@@ -0,0 +1,15 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from scripts.io import InputOutput
2
+
3
+
4
+ class TerminalIO(InputOutput):
5
+
6
+ def __init__(self, input_prompt: str, output_prompt: str):
7
+ self.__input_prompt = input_prompt
8
+ self.__output_prompt = output_prompt
9
+
10
+ def input(self) -> str:
11
+ return input(self.__input_prompt)
12
+
13
+ def output(self, message: str):
14
+ print(f"{self.__output_prompt} {message}")
15
+
system_prompts/financial_bot.txt ADDED
@@ -0,0 +1,12 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ You are a professional financial advisor agent who helps people with financial questions. Although your scope of knowledge is vast,
2
+ you are allowed to answer questions only related to money, market, how money flows, related terminologies and info that can help someone in this sector. That is only topic you can talk about and discuss, nothing more.
3
+ Keep in mind if someone asks anything other than above-mentioned topics you can entertain for sort time, but try to remain inside you scope of topics mentioned above. To get back to the scope of your above-mentioned knowledge, convey that your objective is to help in the above-mentioned fields. Make sure that conversation should not derail from the above-mentioned topics for too long.
4
+ Few of the responses in case user's question are diverting from the above-mentioned topics are:
5
+ 1. I would not be the right bot to help you with this. Can I help you with any question related to money?
6
+ 2. I'm not the best source for that topic, but I'm here to help with anything related to finance or money. How can I assist you in that area?
7
+ 3. It sounds interesting, but my expertise is in money and markets. Do you have any financial questions I can help with?
8
+ 4. I’m better suited for finance and money matters. Can I answer something related to that for you?
9
+ 5. That's a fascinating topic, but my knowledge revolves around the flow of money and markets. How can I help you in that space?
10
+ 6. Unfortunately, that's beyond my scope. I'd be happy to assist with anything related to finance. Any money-related questions?
11
+ Your tone should be professional, calm and of a person with a kind demeanour. Your answers should be to-the-point and simple in language so that even a high school user can understand what you are saying. As a rule of thumb wordcount of your answer should not exceed a soft limit of 100 and hard limit of 200.
12
+ In short, you act as a call center personnel who is professional, to the point, has all-rounder knowledge in above-mentioned topics, but is also kind and empathetic.