-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathchatgpt.py
116 lines (96 loc) · 3.72 KB
/
chatgpt.py
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
import signal
from ai.history.abstract import AbstractCache
from ai.history.file_cache import FileCache, TwoWayFileCache
import ai.openai as openai
import ai.moa as moa
from reactivex import operators as ops
import argparse
import sys
import select
# Just importing this fixes arrow keys in `input`. Side effects ahoy!
# I think this is builtin?
import readline
def respond(query, ai_model, history_manager: AbstractCache):
history = history_manager.load()
collected = ''
def write(sig=None, frame=None):
user_query = [{"role": "user", "content": query}]
assistant_response = [
{"role": "assistant", "content": collected.strip()}]
history["chat"] = history.get(
"chat", []) + user_query + assistant_response
history_manager.write(history)
print()
# exit(0)
def write_and_exit(sig=None, frame=None):
write()
exit(0)
signal.signal(signal.SIGINT, write_and_exit)
def _concat(answer):
nonlocal collected
collected += answer
ai_model.request(query, history.get("chat", [])).pipe(
ops.do_action(lambda answer: print(answer, end='', flush=True)),
ops.do_action(_concat)
).subscribe(
on_completed=write
)
def _get_stdin_data():
# might only work on unix systems?
if select.select([sys.stdin], [], [], 0.0)[0]:
# return sys.stdin.read()
# if not sys.stdin.isatty():
stdin_data = sys.stdin.read()
return "\n\n" + stdin_data
return ""
def _build_query(query: str, stdin_data: str):
if stdin_data:
return query + "\n\n" + stdin_data
return query
def main():
parser = argparse.ArgumentParser()
parser.add_argument('-c', '--clear', action='store_true', default=False)
# `-o` does nothing currently, since phind was removed.
parser.add_argument('-o', '--openai', action='store_true', default=False)
parser.add_argument('-m', '--moa', action='store_true', default=False)
parser.add_argument('-i', '--interactive',
action='store_true', default=False)
parser.add_argument('-q', '--quiet', action='store_true', default=False)
parser.add_argument('--history-from', dest="history_from", type=str, default='',
help="Take conversation history from another conversation")
parser.add_argument('--no-clear', action='store_true', default=False, dest="no_clear",
help="Prevent clearing history.")
parser.add_argument('args', nargs='*')
args = parser.parse_args()
history_manager = TwoWayFileCache(load_file=args.history_from) if args.history_from else FileCache()
query = " ".join(args.args) + _get_stdin_data()
if args.clear or (not query and not args.interactive):
if args.no_clear:
raise Exception("Won't clear history with --no-clear")
history_manager.clear()
if not args.quiet:
print("Cleared history.", file=sys.stderr)
if not query and not args.interactive:
return None
model = openai
if args.moa:
model = moa
if args.interactive:
ctrl_c_counter = 0
while True:
try:
user_input = input(">>> ")
if user_input.lower() == 'exit':
return
respond(user_input, model, history_manager)
ctrl_c_counter = 0
except (EOFError, KeyboardInterrupt):
ctrl_c_counter += 1
if ctrl_c_counter == 2:
return
except Exception as e:
if not args.quiet:
print("An exception occurred:", str(e))
respond(query, model, history_manager)
if __name__ == "__main__":
main()