Skip to content

Commit d4aee09

Browse files
committed
Functions with Class-template
1 parent 4ac1737 commit d4aee09

File tree

4 files changed

+130
-11
lines changed

4 files changed

+130
-11
lines changed

README.md

+10
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,16 @@ If you have added the script to your path, you can run it from anywhere:
5454
![image](https://user-images.githubusercontent.com/3023775/232043124-5bcdc240-4b86-4397-9355-ff0a8dc2f3fe.png)
5555
![image](https://user-images.githubusercontent.com/3023775/232043119-d25b1e93-c99b-48e6-b9c6-ccbc1270a800.png)
5656

57+
Plug-ins
58+
--------
59+
Available from v.0.5.0
60+
61+
You can now define your own Functions. (See OpenAI-chatAPI for details)
62+
63+
Implement them in a Class file, and drop it in the functions directory where OAI is installed.
64+
65+
Your functions/FuncTemplate.txt, is a class template to get you started.
66+
5767
Options
5868
-------
5969

functions/FuncTemplate.txt

+37
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
import requests
2+
import json
3+
import unicodedata
4+
# coding: utf-8
5+
6+
class <My_Func_Class>:
7+
8+
def __init__(self):
9+
self.functions = [
10+
{
11+
"name": "<my_func_name>",
12+
"description": "What it does, for chatGPT to understand",
13+
"parameters": {
14+
"type": "object",
15+
"properties": {
16+
"<param_1>": {
17+
"type": "string",
18+
"description": "The first parameter of <my_func_name>"
19+
},
20+
"<param_2": {
21+
"type": "string",
22+
"description": "The second parameter of <my_func_name"
23+
}
24+
},
25+
"required": [ "<param_1>", "<param_2>" ],
26+
},
27+
}
28+
]
29+
30+
def <my_func_name>(self, <param_1>, <param_2>):
31+
# Note: Any number of parameters can be used for your function.
32+
33+
# Do the function with the parameters available.
34+
35+
# Return with text string, to be sent to ChatGPT from function.
36+
# If no need to call chatGPT any more, return 'stop'. (As in storage)
37+
return 'stop'

oai.py

+71-6
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
import sys
66
import json
77
import io
8+
import importlib, inspect
89

910
from rich import pager
1011
from rich.console import Console
@@ -17,9 +18,13 @@
1718

1819

1920
console = Console()
20-
version = "0.4.1"
21+
version = "0.5.0"
2122
_session_file_ = ".messages.json"
2223

24+
available_parameters = {}
25+
available_descr = {}
26+
available_functions = {}
27+
2328
def get_lindata():
2429
lindata = "Users Kernel:" + platform.platform() + "\n" \
2530
"Users OS:" + os.uname().version + "\n" \
@@ -98,6 +103,25 @@ def extract_jsonstr(prompt):
98103
exit()
99104
return pro
100105

106+
def get_fun_def(func):
107+
108+
for file in os.listdir(os.path.dirname(__file__)+"/functions"):
109+
if file.endswith(".py"):
110+
file_name = file[:-3]
111+
module_name = 'functions.' + file_name
112+
for name, cls in inspect.getmembers(importlib.import_module(module_name), inspect.isclass):
113+
if cls.__module__ == module_name:
114+
if func in dir(cls):
115+
obj = cls()
116+
full = inspect.getfullargspec(getattr(obj, func))
117+
args = ', '.join(full.args)
118+
available_functions[func] = getattr(obj, func)
119+
available_parameters[func] = full.args
120+
available_descr[func] = obj.functions
121+
return available_descr[func][0]
122+
return ""
123+
124+
101125
def main():
102126
desc = "This tool sends a query to OpenAIs Chat API from the command line.\n\n"\
103127
"A new chat session is started with -n <pre-info> and gives the opportunity to\n"\
@@ -115,6 +139,8 @@ def main():
115139

116140
# Add arguments for expert mode, API key reset, version, and prompt
117141
parser.add_argument('-n', '--new', action="store_true", help='Start New Chat', dest='new')
142+
parser.add_argument('-f', '--function', default='', help='Enable function call', dest='function')
143+
# parser.add_argument('name', nargs='?', default="")
118144
parser.add_argument('-l', '--linux', action="store_true", help='Include an assistent message with Kernel/OS/shell', dest='linux')
119145
parser.add_argument('-m', '--model', action="store_true", help='List models available via OpenAIs API', dest='model')
120146
parser.add_argument('-x', '--expert', action="store_true", help='Toggle warning', dest='expert')
@@ -180,23 +206,62 @@ def main():
180206
config.toggle_expert_mode()
181207
sys.exit()
182208

209+
func = ""
210+
if args.function:
211+
func = args.function
212+
if func == "":
213+
print("No function provided. Exiting...")
214+
sys.exit()
215+
func = get_fun_def(func)
216+
if func == "":
217+
print('Function not found: ' + func)
218+
sys.exit()
219+
183220
if not args.prompt:
184221
prompt = Prompt.ask("Documentation Request")
185222
if prompt == "":
186223
print("No prompt provided. Exiting...")
187224
sys.exit()
188225
else:
189226
prompt = args.prompt
227+
askDict = {'role':'user', 'content':prompt}
190228
if os.path.isfile(_session_file_):
191229
messages = get_session()
192-
messages.append({'role':'user', 'content':prompt})
230+
messages.append(askDict)
193231
else:
194-
messages=[{'role':'user', 'content':prompt}]
232+
messages=[askDict]
195233

196234
with console.status(f"Phoning a friend... ", spinner="pong"):
197-
openai_response = post_completion(get_chat(messages))
198-
console.print(Markdown(openai_response.strip()))
199-
messages.append({'role':'assistant', 'content':openai_response.strip()})
235+
openai_response = get_chat(messages, func)
236+
if openai_response.get("function_call"):
237+
function_name = openai_response["function_call"]["name"]
238+
if function_name in available_functions:
239+
fuction_to_call = available_functions[function_name]
240+
else:
241+
print('Bad returned function name from OpenAI API')
242+
print(openai_response)
243+
messages.append(openai_response)
244+
messages.append({"role": "function", "name": function_name, "content": func})
245+
function_args = json.loads(openai_response["function_call"]["arguments"].strip())
246+
console.print(Markdown(function_args.get("content").strip()))
247+
put_session(messages)
248+
exit()
249+
250+
#print(openai_response["function_call"]["arguments"].strip())
251+
function_args = json.loads(openai_response["function_call"]["arguments"].strip())
252+
function_response = fuction_to_call(
253+
heading=function_args.get("heading"),
254+
content=function_args.get("content").strip(),
255+
)
256+
messages.append(openai_response)
257+
messages.append({"role": "function", "name": function_name, "content": function_response})
258+
259+
if function_response != 'stop':
260+
openai_response = get_chat(messages)
261+
else:
262+
openai_response.content = function_args.get("content")
263+
console.print(Markdown(openai_response.content.strip()))
264+
messages.append({'role':'assistant', 'content':openai_response.content.strip()})
200265
put_session(messages)
201266

202267

resources/conduit.py

+12-5
Original file line numberDiff line numberDiff line change
@@ -43,18 +43,25 @@ def get_completion(prompt):
4343
sys.exit()
4444
return response
4545

46-
def get_chat(messages):
46+
def get_chat(messages, func = ""):
4747
openai.api_key = config.get_api_key()
4848
engine = config.get_model()
4949

5050
if len(messages) == 0:
5151
print("Prompt is empty. Please enter a prompt.")
5252

5353
try:
54-
response = openai.ChatCompletion.create(
55-
model=engine,
56-
messages=messages
57-
).choices[0].message.content
54+
if func == "":
55+
response = openai.ChatCompletion.create(
56+
model=engine,
57+
messages=messages
58+
).choices[0].message
59+
else:
60+
response = openai.ChatCompletion.create(
61+
model=engine,
62+
messages=messages,
63+
functions=[func]
64+
).choices[0].message
5865
except openai.error.APIError as e:
5966
# Handle API error here, e.g. retry or log
6067
print(f"OpenAI API returned an API Error: {e}")

0 commit comments

Comments
 (0)