54
54
# $1 should be the response body
55
55
handle_error () {
56
56
if echo " $1 " | jq -e ' .error' > /dev/null; then
57
- echo -e " Your request to Open AI API failed: \033[0;31m$( echo $1 | jq -r ' .error.type' ) \033[0m"
58
- echo $1 | jq -r ' .error.message'
57
+ echo -e " Your request to Open AI API failed: \033[0;31m$( echo " $1 " | jq -r ' .error.type' ) \033[0m"
58
+ echo " $1 " | jq -r ' .error.message'
59
59
exit 1
60
60
fi
61
61
}
62
62
63
63
# request to OpenAI API completions endpoint function
64
64
# $1 should be the request prompt
65
65
request_to_completions () {
66
- request_prompt =" $1 "
66
+ local prompt =" $1 "
67
67
68
- response= $( curl https://api.openai.com/v1/completions \
68
+ curl https://api.openai.com/v1/completions \
69
69
-sS \
70
70
-H ' Content-Type: application/json' \
71
71
-H " Authorization: Bearer $OPENAI_KEY " \
72
72
-d ' {
73
73
"model": "' " $MODEL " ' ",
74
- "prompt": "' " ${request_prompt} " ' ",
74
+ "prompt": "' " $prompt " ' ",
75
75
"max_tokens": ' $MAX_TOKENS ' ,
76
76
"temperature": ' $TEMPERATURE '
77
- }' )
77
+ }'
78
78
}
79
79
80
80
# request to OpenAI API image generations endpoint function
81
81
# $1 should be the prompt
82
82
request_to_image () {
83
- prompt=" $1 "
83
+ local prompt=" $1 "
84
84
image_response=$( curl https://api.openai.com/v1/images/generations \
85
85
-sS \
86
86
-H ' Content-Type: application/json' \
@@ -95,8 +95,8 @@ request_to_image() {
95
95
# request to OpenAPI API chat completion endpoint function
96
96
# $1 should be the message(s) formatted with role and content
97
97
request_to_chat () {
98
- message=" $1 "
99
- response= $( curl https://api.openai.com/v1/chat/completions \
98
+ local message=" $1 "
99
+ curl https://api.openai.com/v1/chat/completions \
100
100
-sS \
101
101
-H ' Content-Type: application/json' \
102
102
-H " Authorization: Bearer $OPENAI_KEY " \
@@ -108,35 +108,36 @@ request_to_chat() {
108
108
],
109
109
"max_tokens": ' $MAX_TOKENS ' ,
110
110
"temperature": ' $TEMPERATURE '
111
- }' )
111
+ }'
112
112
}
113
113
114
114
# build chat context before each request for /completions (all models except
115
115
# gpt turbo and gpt 4)
116
- # $1 should be the chat context
117
- # $2 should be the escaped prompt
116
+ # $1 should be the escaped request prompt,
117
+ # it extends $chat_context
118
118
build_chat_context () {
119
- chat_context=" $1 "
120
- escaped_prompt=" $2 "
119
+ local escaped_request_prompt=" $1 "
121
120
if [ -z " $chat_context " ]; then
122
- chat_context=" $CHAT_INIT_PROMPT \nQ: $escaped_prompt "
121
+ chat_context=" $CHAT_INIT_PROMPT \nQ: $escaped_request_prompt "
123
122
else
124
- chat_context=" $chat_context \nQ: $escaped_prompt "
123
+ chat_context=" $chat_context \nQ: $escaped_request_prompt "
125
124
fi
126
- request_prompt=" ${chat_context// $' \n ' / \\ n} "
125
+ }
126
+
127
+ escape (){
128
+ echo " $1 " | jq -Rrs ' tojson[1:-1]'
127
129
}
128
130
129
131
# maintain chat context function for /completions (all models except
130
132
# gpt turbo and gpt 4)
131
133
# builds chat context from response,
132
134
# keeps chat context length under max token limit
133
- # $1 should be the chat context
134
- # $2 should be the response data (only the text)
135
+ # * $1 should be the escaped response data
136
+ # * it extends $chat_context
135
137
maintain_chat_context () {
136
- chat_context=" $1 "
137
- response_data=" $2 "
138
+ local escaped_response_data=" $1 "
138
139
# add response to chat context as answer
139
- chat_context=" $chat_context ${chat_context: +\n } \nA: ${response_data // $' \n ' / \\ n} "
140
+ chat_context=" $chat_context ${chat_context: +\n } \nA: $escaped_response_data "
140
141
# check prompt length, 1 word =~ 1.3 tokens
141
142
# reserving 100 tokens for next user prompt
142
143
while (( $(echo "$chat_context " | wc - c) * 1 , 3 > (MAX_TOKENS - 100 )) ); do
@@ -149,36 +150,29 @@ maintain_chat_context() {
149
150
150
151
# build user chat message function for /chat/completions (gpt models)
151
152
# builds chat message before request,
152
- # $1 should be the chat message
153
- # $2 should be the escaped prompt
153
+ # $1 should be the escaped request prompt,
154
+ # it extends $chat_message
154
155
build_user_chat_message () {
155
- chat_message=" $1 "
156
- escaped_prompt=" $2 "
156
+ local escaped_request_prompt=" $1 "
157
157
if [ -z " $chat_message " ]; then
158
- chat_message=" {\" role\" : \" user\" , \" content\" : \" $escaped_prompt \" }"
158
+ chat_message=" {\" role\" : \" user\" , \" content\" : \" $escaped_request_prompt \" }"
159
159
else
160
- chat_message=" $chat_message , {\" role\" : \" user\" , \" content\" : \" $escaped_prompt \" }"
160
+ chat_message=" $chat_message , {\" role\" : \" user\" , \" content\" : \" $escaped_request_prompt \" }"
161
161
fi
162
-
163
- request_prompt=" $chat_message "
164
162
}
165
163
166
164
# adds the assistant response to the message in (chatml) format
167
165
# for /chat/completions (gpt models)
168
166
# keeps messages length under max token limit
169
- # $1 should be the chat message
170
- # $2 should be the response data (only the text)
167
+ # * $1 should be the escaped response data
168
+ # * it extends and potentially shrinks $chat_message
171
169
add_assistant_response_to_chat_message () {
172
- chat_message=" $1 "
173
- local local_response_data=" $2 "
174
-
175
- # replace new line characters from response with space
176
- local_response_data=$( echo " $local_response_data " | tr ' \n' ' ' )
170
+ local escaped_response_data=" $1 "
177
171
# add response to chat context as answer
178
- chat_message=" $chat_message , {\" role\" : \" assistant\" , \" content\" : \" $local_response_data \" }"
172
+ chat_message=" $chat_message , {\" role\" : \" assistant\" , \" content\" : \" $escaped_response_data \" }"
179
173
180
174
# transform to json array to parse with jq
181
- chat_message_json=" [ $chat_message ]"
175
+ local chat_message_json=" [ $chat_message ]"
182
176
# check prompt length, 1 word =~ 1.3 tokens
183
177
# reserving 100 tokens for next user prompt
184
178
while (( $(echo "$chat_message " | wc - c) * 1 , 3 > (MAX_TOKENS - 100 )) ); do
@@ -296,7 +290,7 @@ while $running; do
296
290
elif [[ " $prompt " =~ ^image: ]]; then
297
291
request_to_image " $prompt "
298
292
handle_error " $image_response "
299
- image_url=$( echo $image_response | jq -r ' .data[0].url' )
293
+ image_url=$( echo " $image_response " | jq -r ' .data[0].url' )
300
294
echo -e " $OVERWRITE_PROCESSING_LINE "
301
295
echo -e " ${CHATGPT_CYAN_LABEL} Your image was created. \n\nLink: ${image_url} \n"
302
296
@@ -334,15 +328,12 @@ while $running; do
334
328
echo -e " $OVERWRITE_PROCESSING_LINE "
335
329
echo -e " ${CHATGPT_CYAN_LABEL} Complete details for model: ${prompt#* model: } \n ${model_data} "
336
330
elif [[ " $prompt " =~ ^command: ]]; then
337
- # escape quotation marks
338
- escaped_prompt=$( echo " $prompt " | sed ' s/"/\\"/g' )
339
- # escape new lines
340
- if [[ " $prompt " =~ ^command: ]]; then
341
- escaped_prompt=${prompt# command: }
342
- request_prompt=$COMMAND_GENERATION_PROMPT ${escaped_prompt// $' \n ' / ' ' }
343
- fi
344
- build_user_chat_message " $chat_message " " $request_prompt "
345
- request_to_chat " $request_prompt "
331
+ # escape quotation marks, new lines, backslashes...
332
+ escaped_prompt=$( escape " $prompt " )
333
+ escaped_prompt=${escaped_prompt# command: }
334
+ request_prompt=$COMMAND_GENERATION_PROMPT$escaped_prompt
335
+ build_user_chat_message " $request_prompt "
336
+ response=$( request_to_chat " $chat_message " )
346
337
handle_error " $response "
347
338
response_data=$( echo $response | jq -r ' .choices[].message.content' )
348
339
@@ -363,20 +354,17 @@ while $running; do
363
354
eval $response_data
364
355
fi
365
356
fi
366
- escaped_response_data=$( echo " $response_data " | sed ' s/"/\\"/g' )
367
- add_assistant_response_to_chat_message " $chat_message " " $escaped_response_data "
357
+ add_assistant_response_to_chat_message " $( escape " $response_data " ) "
368
358
369
359
timestamp=$( date +" %d/%m/%Y %H:%M" )
370
360
echo -e " $timestamp $prompt \n$response_data \n" >> ~/.chatgpt_history
371
361
372
362
elif [[ " $MODEL " =~ ^gpt- ]]; then
373
- # escape quotation marks
374
- escaped_prompt=$( echo " $prompt " | sed ' s/"/\\"/g' )
375
- # escape new lines
376
- request_prompt=${escaped_prompt// $' \n ' / ' ' }
363
+ # escape quotation marks, new lines, backslashes...
364
+ request_prompt=$( escape " $prompt " )
377
365
378
- build_user_chat_message " $chat_message " " $ request_prompt"
379
- request_to_chat " $request_prompt "
366
+ build_user_chat_message " $request_prompt "
367
+ response= $( request_to_chat " $chat_message " )
380
368
handle_error " $response "
381
369
response_data=$( echo " $response " | jq -r ' .choices[].message.content' )
382
370
@@ -387,24 +375,21 @@ while $running; do
387
375
echo " ${response_data} " | glow -
388
376
# echo -e "${formatted_text}"
389
377
else
390
- echo -e " ${CHATGPT_CYAN_LABEL}${response_data} " | fold -s -w $COLUMNS
378
+ echo -e " ${CHATGPT_CYAN_LABEL}${response_data} " | fold -s -w " $COLUMNS "
391
379
fi
392
- escaped_response_data=$( echo " $response_data " | sed ' s/"/\\"/g' )
393
- add_assistant_response_to_chat_message " $chat_message " " $escaped_response_data "
380
+ add_assistant_response_to_chat_message " $( escape " $response_data " ) "
394
381
395
382
timestamp=$( date +" %d/%m/%Y %H:%M" )
396
383
echo -e " $timestamp $prompt \n$response_data \n" >> ~/.chatgpt_history
397
384
else
398
- # escape quotation marks
399
- escaped_prompt=$( echo " $prompt " | sed ' s/"/\\"/g' )
400
- # escape new lines
401
- request_prompt=${escaped_prompt// $' \n ' / ' ' }
385
+ # escape quotation marks, new lines, backslashes...
386
+ request_prompt=$( escape " $prompt " )
402
387
403
388
if [ " $CONTEXT " = true ]; then
404
- build_chat_context " $chat_context " " $escaped_prompt "
389
+ build_chat_context " $request_prompt "
405
390
fi
406
391
407
- request_to_completions " $request_prompt "
392
+ response= $( request_to_completions " $request_prompt " )
408
393
handle_error " $response "
409
394
response_data=$( echo " $response " | jq -r ' .choices[].text' )
410
395
@@ -420,8 +405,7 @@ while $running; do
420
405
fi
421
406
422
407
if [ " $CONTEXT " = true ]; then
423
- escaped_response_data=$( echo " $response_data " | sed ' s/"/\\"/g' )
424
- maintain_chat_context " $chat_context " " $escaped_response_data "
408
+ maintain_chat_context " $( escape " $response_data " ) "
425
409
fi
426
410
427
411
timestamp=$( date +" %d/%m/%Y %H:%M" )
0 commit comments