push v3.4.3 files
Browse files- README.md +1 -1
- custom_classes/messages.py +0 -54
- handlers/json_handler.py +7 -4
- models/kaiseki.py +19 -8
- models/kijiku.py +88 -234
- modules/common/exceptions.py +13 -5
- modules/common/file_ensurer.py +1 -33
- modules/common/toolkit.py +1 -1
- requirements.txt +1 -4
- translation_services/deepl_service.py +0 -85
- translation_services/gemini_service.py +0 -215
- translation_services/openai_service.py +0 -180
- util/token_counter.py +13 -31
- webgui.py +16 -21
README.md
CHANGED
@@ -32,7 +32,7 @@ This readme is for the Hugging Space instance of Kudasai's WebGUI and the WebGUI
|
|
32 |
|
33 |
Streamlining Japanese-English Translation with Advanced Preprocessing and Integrated Translation Technologies.
|
34 |
|
35 |
-
Preprocessor is sourced from
|
36 |
|
37 |
Kudasai has a public trello board, you can find it [here](https://trello.com/b/Wsuwr24S/kudasai) to see what I'm working on.
|
38 |
|
|
|
32 |
|
33 |
Streamlining Japanese-English Translation with Advanced Preprocessing and Integrated Translation Technologies.
|
34 |
|
35 |
+
Preprocessor and Translation logic is sourced from external packages, which I also designed, see [Kairyou](https://github.com/Bikatr7/Kairyou) and [EasyTL](https://github.com/Bikatr7/easytl) for more information.
|
36 |
|
37 |
Kudasai has a public trello board, you can find it [here](https://trello.com/b/Wsuwr24S/kudasai) to see what I'm working on.
|
38 |
|
custom_classes/messages.py
DELETED
@@ -1,54 +0,0 @@
|
|
1 |
-
##-------------------start-of-Message--------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
2 |
-
|
3 |
-
class Message:
|
4 |
-
|
5 |
-
"""
|
6 |
-
|
7 |
-
Message is a class that is used to send translation batches to the OpenAI API.
|
8 |
-
|
9 |
-
"""
|
10 |
-
|
11 |
-
def __init__(self, content: str):
|
12 |
-
self._content = content
|
13 |
-
|
14 |
-
@property
|
15 |
-
def role(self):
|
16 |
-
raise NotImplementedError
|
17 |
-
|
18 |
-
@property
|
19 |
-
def content(self):
|
20 |
-
return self._content
|
21 |
-
|
22 |
-
def to_dict(self):
|
23 |
-
return {
|
24 |
-
'role': self.role,
|
25 |
-
'content': self.content
|
26 |
-
}
|
27 |
-
|
28 |
-
##-------------------start-of-SystemTranslationMessage--------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
29 |
-
|
30 |
-
class SystemTranslationMessage(Message):
|
31 |
-
|
32 |
-
"""
|
33 |
-
|
34 |
-
SystemTranslationMessage is a class that is used to send the system message to the OpenAI API.
|
35 |
-
|
36 |
-
"""
|
37 |
-
|
38 |
-
@property
|
39 |
-
def role(self):
|
40 |
-
return 'system'
|
41 |
-
|
42 |
-
##-------------------start-of-ModelTranslationMessage--------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
43 |
-
|
44 |
-
class ModelTranslationMessage(Message):
|
45 |
-
|
46 |
-
"""
|
47 |
-
|
48 |
-
ModelTranslationMessage is a class that is used to send the model/user message to the OpenAI API.
|
49 |
-
|
50 |
-
"""
|
51 |
-
|
52 |
-
@property
|
53 |
-
def role(self):
|
54 |
-
return 'user'
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
handlers/json_handler.py
CHANGED
@@ -2,6 +2,9 @@
|
|
2 |
import json
|
3 |
import typing
|
4 |
|
|
|
|
|
|
|
5 |
## custom modules
|
6 |
from modules.common.file_ensurer import FileEnsurer
|
7 |
from modules.common.logger import Logger
|
@@ -144,13 +147,13 @@ gemini_stream, gemini_stop_sequences and gemini_candidate_count are included for
|
|
144 |
"number_of_malformed_batch_retries": lambda x: isinstance(x, int) and x >= 0,
|
145 |
"batch_retry_timeout": lambda x: isinstance(x, int) and x >= 0,
|
146 |
"number_of_concurrent_batches": lambda x: isinstance(x, int) and x >= 0,
|
147 |
-
"openai_model": lambda x: isinstance(x, str) and x in
|
148 |
"openai_system_message": lambda x: x not in ["", "None", None],
|
149 |
"openai_temperature": lambda x: isinstance(x, float) and 0 <= x <= 2,
|
150 |
"openai_top_p": lambda x: isinstance(x, float) and 0 <= x <= 1,
|
151 |
"openai_max_tokens": lambda x: x is None or isinstance(x, int) and x > 0,
|
152 |
"openai_presence_penalty": lambda x: isinstance(x, float) and -2 <= x <= 2,
|
153 |
-
"gemini_model": lambda x: isinstance(x, str) and x in
|
154 |
"gemini_prompt": lambda x: x not in ["", "None", None],
|
155 |
"gemini_temperature": lambda x: isinstance(x, float) and 0 <= x <= 2,
|
156 |
"gemini_top_p": lambda x: x is None or (isinstance(x, float) and 0 <= x <= 2),
|
@@ -360,7 +363,7 @@ gemini_stream, gemini_stop_sequences and gemini_candidate_count are included for
|
|
360 |
"number_of_malformed_batch_retries": {"type": int, "constraints": lambda x: x >= 0},
|
361 |
"batch_retry_timeout": {"type": int, "constraints": lambda x: x >= 0},
|
362 |
"number_of_concurrent_batches": {"type": int, "constraints": lambda x: x >= 0},
|
363 |
-
"openai_model": {"type": str, "constraints": lambda x: x in
|
364 |
"openai_system_message": {"type": str, "constraints": lambda x: x not in ["", "None", None]},
|
365 |
"openai_temperature": {"type": float, "constraints": lambda x: 0 <= x <= 2},
|
366 |
"openai_top_p": {"type": float, "constraints": lambda x: 0 <= x <= 2},
|
@@ -371,7 +374,7 @@ gemini_stream, gemini_stop_sequences and gemini_candidate_count are included for
|
|
371 |
"openai_max_tokens": {"type": int, "constraints": lambda x: x is None or isinstance(x, int)},
|
372 |
"openai_presence_penalty": {"type": float, "constraints": lambda x: -2 <= x <= 2},
|
373 |
"openai_frequency_penalty": {"type": float, "constraints": lambda x: -2 <= x <= 2},
|
374 |
-
"gemini_model": {"type": str, "constraints": lambda x: x in
|
375 |
"gemini_prompt": {"type": str, "constraints": lambda x: x not in ["", "None", None]},
|
376 |
"gemini_temperature": {"type": float, "constraints": lambda x: 0 <= x <= 2},
|
377 |
"gemini_top_p": {"type": float, "constraints": lambda x: x is None or (isinstance(x, float) and 0 <= x <= 2)},
|
|
|
2 |
import json
|
3 |
import typing
|
4 |
|
5 |
+
## third-party libraries
|
6 |
+
from easytl import ALLOWED_GEMINI_MODELS, ALLOWED_OPENAI_MODELS
|
7 |
+
|
8 |
## custom modules
|
9 |
from modules.common.file_ensurer import FileEnsurer
|
10 |
from modules.common.logger import Logger
|
|
|
147 |
"number_of_malformed_batch_retries": lambda x: isinstance(x, int) and x >= 0,
|
148 |
"batch_retry_timeout": lambda x: isinstance(x, int) and x >= 0,
|
149 |
"number_of_concurrent_batches": lambda x: isinstance(x, int) and x >= 0,
|
150 |
+
"openai_model": lambda x: isinstance(x, str) and x in ALLOWED_OPENAI_MODELS,
|
151 |
"openai_system_message": lambda x: x not in ["", "None", None],
|
152 |
"openai_temperature": lambda x: isinstance(x, float) and 0 <= x <= 2,
|
153 |
"openai_top_p": lambda x: isinstance(x, float) and 0 <= x <= 1,
|
154 |
"openai_max_tokens": lambda x: x is None or isinstance(x, int) and x > 0,
|
155 |
"openai_presence_penalty": lambda x: isinstance(x, float) and -2 <= x <= 2,
|
156 |
+
"gemini_model": lambda x: isinstance(x, str) and x in ALLOWED_GEMINI_MODELS,
|
157 |
"gemini_prompt": lambda x: x not in ["", "None", None],
|
158 |
"gemini_temperature": lambda x: isinstance(x, float) and 0 <= x <= 2,
|
159 |
"gemini_top_p": lambda x: x is None or (isinstance(x, float) and 0 <= x <= 2),
|
|
|
363 |
"number_of_malformed_batch_retries": {"type": int, "constraints": lambda x: x >= 0},
|
364 |
"batch_retry_timeout": {"type": int, "constraints": lambda x: x >= 0},
|
365 |
"number_of_concurrent_batches": {"type": int, "constraints": lambda x: x >= 0},
|
366 |
+
"openai_model": {"type": str, "constraints": lambda x: x in ALLOWED_OPENAI_MODELS},
|
367 |
"openai_system_message": {"type": str, "constraints": lambda x: x not in ["", "None", None]},
|
368 |
"openai_temperature": {"type": float, "constraints": lambda x: 0 <= x <= 2},
|
369 |
"openai_top_p": {"type": float, "constraints": lambda x: 0 <= x <= 2},
|
|
|
374 |
"openai_max_tokens": {"type": int, "constraints": lambda x: x is None or isinstance(x, int)},
|
375 |
"openai_presence_penalty": {"type": float, "constraints": lambda x: -2 <= x <= 2},
|
376 |
"openai_frequency_penalty": {"type": float, "constraints": lambda x: -2 <= x <= 2},
|
377 |
+
"gemini_model": {"type": str, "constraints": lambda x: x in ALLOWED_GEMINI_MODELS},
|
378 |
"gemini_prompt": {"type": str, "constraints": lambda x: x not in ["", "None", None]},
|
379 |
"gemini_temperature": {"type": float, "constraints": lambda x: 0 <= x <= 2},
|
380 |
"gemini_top_p": {"type": float, "constraints": lambda x: x is None or (isinstance(x, float) and 0 <= x <= 2)},
|
models/kaiseki.py
CHANGED
@@ -1,5 +1,6 @@
|
|
1 |
## Basically Deprecated, use Kijiku instead. Currently only maintained for backwards compatibility.
|
2 |
##---------------------------------------
|
|
|
3 |
## built-in libraries
|
4 |
import string
|
5 |
import time
|
@@ -7,8 +8,10 @@ import re
|
|
7 |
import base64
|
8 |
import time
|
9 |
|
|
|
|
|
|
|
10 |
## custom modules
|
11 |
-
from translation_services.deepl_service import DeepLService
|
12 |
from modules.common.toolkit import Toolkit
|
13 |
from modules.common.file_ensurer import FileEnsurer
|
14 |
from modules.common.logger import Logger
|
@@ -105,8 +108,10 @@ class Kaiseki:
|
|
105 |
with open(FileEnsurer.deepl_api_key_path, 'r', encoding='utf-8') as file:
|
106 |
api_key = base64.b64decode((file.read()).encode('utf-8')).decode('utf-8')
|
107 |
|
108 |
-
|
109 |
-
|
|
|
|
|
110 |
|
111 |
Logger.log_action("Used saved api key in " + FileEnsurer.deepl_api_key_path, output=True)
|
112 |
|
@@ -118,8 +123,10 @@ class Kaiseki:
|
|
118 |
## if valid save the api key
|
119 |
try:
|
120 |
|
121 |
-
|
122 |
-
|
|
|
|
|
123 |
|
124 |
time.sleep(.1)
|
125 |
|
@@ -136,7 +143,7 @@ class Kaiseki:
|
|
136 |
|
137 |
Toolkit.pause_console()
|
138 |
|
139 |
-
raise e
|
140 |
|
141 |
## other error, alert user and raise it
|
142 |
except Exception as e:
|
@@ -452,7 +459,9 @@ class Kaiseki:
|
|
452 |
single_quote_active = True
|
453 |
|
454 |
try:
|
455 |
-
results =
|
|
|
|
|
456 |
|
457 |
translated_part = results.rstrip(''.join(c for c in string.punctuation if c not in "'\""))
|
458 |
translated_part = translated_part.rstrip()
|
@@ -464,7 +473,9 @@ class Kaiseki:
|
|
464 |
|
465 |
## translates the quote and re-adds it back to the sentence part
|
466 |
if(single_quote_active == True):
|
467 |
-
|
|
|
|
|
468 |
|
469 |
quote = quote.rstrip(''.join(c for c in string.punctuation if c not in "'\""))
|
470 |
quote = quote.rstrip()
|
|
|
1 |
## Basically Deprecated, use Kijiku instead. Currently only maintained for backwards compatibility.
|
2 |
##---------------------------------------
|
3 |
+
##---------------------------------------
|
4 |
## built-in libraries
|
5 |
import string
|
6 |
import time
|
|
|
8 |
import base64
|
9 |
import time
|
10 |
|
11 |
+
## third-party libraries
|
12 |
+
from easytl import EasyTL
|
13 |
+
|
14 |
## custom modules
|
|
|
15 |
from modules.common.toolkit import Toolkit
|
16 |
from modules.common.file_ensurer import FileEnsurer
|
17 |
from modules.common.logger import Logger
|
|
|
108 |
with open(FileEnsurer.deepl_api_key_path, 'r', encoding='utf-8') as file:
|
109 |
api_key = base64.b64decode((file.read()).encode('utf-8')).decode('utf-8')
|
110 |
|
111 |
+
EasyTL.set_api_key("deepl", api_key)
|
112 |
+
is_valid, e = EasyTL.test_api_key_validity("deepl")
|
113 |
+
|
114 |
+
assert is_valid == True, e
|
115 |
|
116 |
Logger.log_action("Used saved api key in " + FileEnsurer.deepl_api_key_path, output=True)
|
117 |
|
|
|
123 |
## if valid save the api key
|
124 |
try:
|
125 |
|
126 |
+
EasyTL.set_api_key("deepl", api_key)
|
127 |
+
is_valid, e = EasyTL.test_api_key_validity("deepl")
|
128 |
+
|
129 |
+
assert is_valid, e
|
130 |
|
131 |
time.sleep(.1)
|
132 |
|
|
|
143 |
|
144 |
Toolkit.pause_console()
|
145 |
|
146 |
+
raise e # type: ignore
|
147 |
|
148 |
## other error, alert user and raise it
|
149 |
except Exception as e:
|
|
|
459 |
single_quote_active = True
|
460 |
|
461 |
try:
|
462 |
+
results = EasyTL.deepl_translate(text=Kaiseki.sentence_parts[i], source_lang= "JA", target_lang="EN-US")
|
463 |
+
|
464 |
+
assert isinstance(results, str), "ValueError: " + str(results)
|
465 |
|
466 |
translated_part = results.rstrip(''.join(c for c in string.punctuation if c not in "'\""))
|
467 |
translated_part = translated_part.rstrip()
|
|
|
473 |
|
474 |
## translates the quote and re-adds it back to the sentence part
|
475 |
if(single_quote_active == True):
|
476 |
+
results = EasyTL.deepl_translate(text=Kaiseki.sentence_parts[i], source_lang= "JA", target_lang="EN-US")
|
477 |
+
|
478 |
+
assert isinstance(results, str), "ValueError: " + str(results)
|
479 |
|
480 |
quote = quote.rstrip(''.join(c for c in string.punctuation if c not in "'\""))
|
481 |
quote = quote.rstrip()
|
models/kijiku.py
CHANGED
@@ -9,8 +9,8 @@ import os
|
|
9 |
|
10 |
## third party modules
|
11 |
from kairyou import KatakanaUtil
|
|
|
12 |
|
13 |
-
import tiktoken
|
14 |
import backoff
|
15 |
|
16 |
## custom modules
|
@@ -22,11 +22,6 @@ from modules.common.toolkit import Toolkit
|
|
22 |
from modules.common.exceptions import AuthenticationError, MaxBatchDurationExceededException, AuthenticationError, InternalServerError, RateLimitError, APITimeoutError, GoogleAuthError
|
23 |
from modules.common.decorators import permission_error_decorator
|
24 |
|
25 |
-
from custom_classes.messages import SystemTranslationMessage, ModelTranslationMessage, Message
|
26 |
-
|
27 |
-
from translation_services.openai_service import OpenAIService
|
28 |
-
from translation_services.gemini_service import GeminiService
|
29 |
-
|
30 |
##-------------------start-of-Kijiku--------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
31 |
|
32 |
class Kijiku:
|
@@ -48,7 +43,7 @@ class Kijiku:
|
|
48 |
|
49 |
## the messages that will be sent to the api, contains a system message and a model message, system message is the instructions,
|
50 |
## model message is the text that will be translated
|
51 |
-
openai_translation_batches:typing.List[
|
52 |
|
53 |
## meanwhile for gemini, we just need to send the prompt and the text to be translated concatenated together
|
54 |
gemini_translation_batches:typing.List[str] = []
|
@@ -74,6 +69,8 @@ class Kijiku:
|
|
74 |
batch_retry_timeout:float
|
75 |
num_concurrent_batches:int
|
76 |
|
|
|
|
|
77 |
##-------------------start-of-get_max_batch_duration()---------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
78 |
|
79 |
@staticmethod
|
@@ -196,10 +193,10 @@ class Kijiku:
|
|
196 |
Toolkit.clear_console()
|
197 |
|
198 |
if(Kijiku.LLM_TYPE == "openai"):
|
199 |
-
await Kijiku.init_api_key("OpenAI", FileEnsurer.openai_api_key_path,
|
200 |
|
201 |
else:
|
202 |
-
await Kijiku.init_api_key("Gemini", FileEnsurer.gemini_api_key_path,
|
203 |
|
204 |
## try to load the kijiku rules
|
205 |
try:
|
@@ -232,17 +229,14 @@ class Kijiku:
|
|
232 |
|
233 |
"""
|
234 |
|
235 |
-
if(service != "OpenAI"):
|
236 |
-
GeminiService.redefine_client()
|
237 |
-
|
238 |
## get saved API key if exists
|
239 |
try:
|
240 |
with open(api_key_path, 'r', encoding='utf-8') as file:
|
241 |
api_key = base64.b64decode((file.read()).encode('utf-8')).decode('utf-8')
|
242 |
|
243 |
-
api_key_setter(api_key)
|
244 |
|
245 |
-
is_valid, e =
|
246 |
|
247 |
## if not valid, raise the exception that caused the test to fail
|
248 |
if(not is_valid and e is not None):
|
@@ -263,9 +257,9 @@ class Kijiku:
|
|
263 |
## if valid save the API key
|
264 |
try:
|
265 |
|
266 |
-
api_key_setter(api_key)
|
267 |
|
268 |
-
is_valid, e =
|
269 |
|
270 |
if(not is_valid and e is not None):
|
271 |
raise e
|
@@ -365,14 +359,14 @@ class Kijiku:
|
|
365 |
if(os.path.exists(FileEnsurer.openai_api_key_path)):
|
366 |
|
367 |
os.remove(FileEnsurer.openai_api_key_path)
|
368 |
-
await Kijiku.init_api_key("OpenAI", FileEnsurer.openai_api_key_path,
|
369 |
|
370 |
else:
|
371 |
|
372 |
if(os.path.exists(FileEnsurer.gemini_api_key_path)):
|
373 |
|
374 |
os.remove(FileEnsurer.gemini_api_key_path)
|
375 |
-
await Kijiku.init_api_key("Gemini", FileEnsurer.gemini_api_key_path,
|
376 |
|
377 |
Toolkit.clear_console()
|
378 |
|
@@ -409,41 +403,34 @@ class Kijiku:
|
|
409 |
|
410 |
Kijiku._semaphore = asyncio.Semaphore(Kijiku.num_concurrent_batches)
|
411 |
|
412 |
-
|
413 |
-
|
414 |
-
|
415 |
-
|
416 |
-
|
417 |
-
|
418 |
-
|
419 |
-
|
420 |
-
|
421 |
-
|
422 |
-
|
423 |
-
|
424 |
-
|
425 |
-
|
426 |
-
|
427 |
-
|
428 |
-
|
429 |
-
|
430 |
-
|
431 |
-
|
432 |
-
|
433 |
|
434 |
-
if(Kijiku.LLM_TYPE == "openai"):
|
435 |
|
436 |
-
|
437 |
-
decorator_to_use = backoff.on_exception(backoff.expo, max_time=lambda: Kijiku.get_max_batch_duration(), exception=(AuthenticationError, InternalServerError, RateLimitError, APITimeoutError), on_backoff=lambda details: Kijiku.log_retry(details), on_giveup=lambda details: Kijiku.log_failure(details), raise_on_giveup=False)
|
438 |
-
|
439 |
-
OpenAIService.set_decorator(decorator_to_use)
|
440 |
|
441 |
else:
|
442 |
-
|
443 |
-
decorator_to_use = backoff.on_exception(backoff.expo, max_time=lambda: Kijiku.get_max_batch_duration(), exception=(Exception), on_backoff=lambda details: Kijiku.log_retry(details), on_giveup=lambda details: Kijiku.log_failure(details), raise_on_giveup=False)
|
444 |
-
|
445 |
-
GeminiService.redefine_client()
|
446 |
-
GeminiService.set_decorator(decorator_to_use)
|
447 |
|
448 |
Toolkit.clear_console()
|
449 |
|
@@ -453,7 +440,7 @@ class Kijiku:
|
|
453 |
|
454 |
Kijiku.build_translation_batches()
|
455 |
|
456 |
-
model =
|
457 |
|
458 |
await Kijiku.handle_cost_estimate_prompt(model, omit_prompt=is_webgui)
|
459 |
|
@@ -519,7 +506,14 @@ class Kijiku:
|
|
519 |
translation_batches = Kijiku.openai_translation_batches if Kijiku.LLM_TYPE == "openai" else Kijiku.gemini_translation_batches
|
520 |
|
521 |
for i in range(0, len(translation_batches), 2):
|
522 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
523 |
|
524 |
return async_requests
|
525 |
|
@@ -601,16 +595,16 @@ class Kijiku:
|
|
601 |
if(Kijiku.LLM_TYPE == 'openai'):
|
602 |
|
603 |
if(Kijiku.prompt_assembly_mode == 1):
|
604 |
-
system_msg = SystemTranslationMessage(content=str(
|
605 |
else:
|
606 |
-
system_msg =
|
607 |
|
608 |
Kijiku.openai_translation_batches.append(system_msg)
|
609 |
model_msg = ModelTranslationMessage(content=batch)
|
610 |
Kijiku.openai_translation_batches.append(model_msg)
|
611 |
|
612 |
else:
|
613 |
-
Kijiku.gemini_translation_batches.append(
|
614 |
Kijiku.gemini_translation_batches.append(batch)
|
615 |
|
616 |
Logger.log_barrier()
|
@@ -630,177 +624,6 @@ class Kijiku:
|
|
630 |
|
631 |
Logger.log_action(message)
|
632 |
|
633 |
-
##-------------------start-of-estimate_cost()---------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
634 |
-
|
635 |
-
@staticmethod
|
636 |
-
def estimate_cost(model:str, price_case:int | None = None) -> typing.Tuple[int, float, str]:
|
637 |
-
|
638 |
-
"""
|
639 |
-
|
640 |
-
Attempts to estimate cost.
|
641 |
-
|
642 |
-
Parameters:
|
643 |
-
model (string) : the model used to translate the text.
|
644 |
-
price_case (int) : the price case used to calculate the cost.
|
645 |
-
|
646 |
-
Returns:
|
647 |
-
num_tokens (int) : the number of tokens used.
|
648 |
-
min_cost (float) : the minimum cost of translation.
|
649 |
-
model (string) : the model used to translate the text.
|
650 |
-
|
651 |
-
"""
|
652 |
-
|
653 |
-
MODEL_COSTS = {
|
654 |
-
"gpt-3.5-turbo": {"price_case": 2, "input_cost": 0.0010, "output_cost": 0.0020},
|
655 |
-
"gpt-4": {"price_case": 4, "input_cost": 0.01, "output_cost": 0.03},
|
656 |
-
"gpt-4-turbo-preview": {"price_case": 4, "input_cost": 0.01, "output_cost": 0.03},
|
657 |
-
"gpt-3.5-turbo-0613": {"price_case": 1, "input_cost": 0.0015, "output_cost": 0.0020},
|
658 |
-
"gpt-3.5-turbo-0301": {"price_case": 1, "input_cost": 0.0015, "output_cost": 0.0020},
|
659 |
-
"gpt-3.5-turbo-1106": {"price_case": 2, "input_cost": 0.0010, "output_cost": 0.0020},
|
660 |
-
"gpt-3.5-turbo-0125": {"price_case": 7, "input_cost": 0.0005, "output_cost": 0.0015},
|
661 |
-
"gpt-3.5-turbo-16k-0613": {"price_case": 3, "input_cost": 0.0030, "output_cost": 0.0040},
|
662 |
-
"gpt-4-1106-preview": {"price_case": 4, "input_cost": 0.01, "output_cost": 0.03},
|
663 |
-
"gpt-4-0125-preview": {"price_case": 4, "input_cost": 0.01, "output_cost": 0.03},
|
664 |
-
"gpt-4-0314": {"price_case": 5, "input_cost": 0.03, "output_cost": 0.06},
|
665 |
-
"gpt-4-0613": {"price_case": 5, "input_cost": 0.03, "output_cost": 0.06},
|
666 |
-
"gpt-4-32k-0314": {"price_case": 6, "input_cost": 0.06, "output_cost": 0.012},
|
667 |
-
"gpt-4-32k-0613": {"price_case": 6, "input_cost": 0.06, "output_cost": 0.012},
|
668 |
-
"gemini-1.0-pro-001": {"price_case": 8, "input_cost": 0.0, "output_cost": 0.0},
|
669 |
-
"gemini-1.0-pro-vision-001": {"price_case": 8, "input_cost": 0.0, "output_cost": 0.0},
|
670 |
-
"gemini-1.0-pro": {"price_case": 8, "input_cost": 0.0, "output_cost": 0.0},
|
671 |
-
"gemini-1.0-pro-vision": {"price_case": 8, "input_cost": 0.0, "output_cost": 0.0},
|
672 |
-
"gemini-1.0-pro-latest": {"price_case": 8, "input_cost": 0.0, "output_cost": 0.0},
|
673 |
-
"gemini-1.0-pro-vision-latest": {"price_case": 8, "input_cost": 0.0, "output_cost": 0.0},
|
674 |
-
"gemini-1.5-pro-latest": {"price_case": 8, "input_cost": 0.0, "output_cost": 0.0},
|
675 |
-
"gemini-1.0-ultra-latest": {"price_case": 8, "input_cost": 0.0, "output_cost": 0.0},
|
676 |
-
"gemini-pro": {"price_case": 8, "input_cost": 0.0, "output_cost": 0.0},
|
677 |
-
"gemini-pro-vision": {"price_case": 8, "input_cost": 0.0, "output_cost": 0.0},
|
678 |
-
"gemini-ultra": {"price_case": 8, "input_cost": 0.0, "output_cost": 0.0}
|
679 |
-
}
|
680 |
-
|
681 |
-
assert model in FileEnsurer.ALLOWED_OPENAI_MODELS or model in FileEnsurer.ALLOWED_GEMINI_MODELS, f"""Kudasai does not support : {model}"""
|
682 |
-
|
683 |
-
## default models are first, then the rest are sorted by price case
|
684 |
-
if(price_case is None):
|
685 |
-
|
686 |
-
if(model == "gpt-3.5-turbo"):
|
687 |
-
print("Warning: gpt-3.5-turbo may change over time. Returning num tokens assuming gpt-3.5-turbo-1106 as it is the most recent version of gpt-3.5-turbo.")
|
688 |
-
return Kijiku.estimate_cost("gpt-3.5-turbo-1106", price_case=2)
|
689 |
-
|
690 |
-
elif(model == "gpt-4"):
|
691 |
-
print("Warning: gpt-4 may change over time. Returning num tokens assuming gpt-4-1106-preview as it is the most recent version of gpt-4.")
|
692 |
-
return Kijiku.estimate_cost("gpt-4-1106-preview", price_case=4)
|
693 |
-
|
694 |
-
elif(model == "gpt-4-turbo-preview"):
|
695 |
-
print("Warning: gpt-4-turbo-preview may change over time. Returning num tokens assuming gpt-4-0125-preview as it is the most recent version of gpt-4-turbo-preview.")
|
696 |
-
return Kijiku.estimate_cost("gpt-4-0125-preview", price_case=4)
|
697 |
-
|
698 |
-
elif(model == "gpt-3.5-turbo-0613"):
|
699 |
-
print("Warning: gpt-3.5-turbo-0613 is considered depreciated by OpenAI as of November 6, 2023 and could be shutdown as early as June 13, 2024. Consider switching to gpt-3.5-turbo-1106.")
|
700 |
-
return Kijiku.estimate_cost(model, price_case=1)
|
701 |
-
|
702 |
-
elif(model == "gpt-3.5-turbo-0301"):
|
703 |
-
print("Warning: gpt-3.5-turbo-0301 is considered depreciated by OpenAI as of June 13, 2023 and could be shutdown as early as June 13, 2024. Consider switching to gpt-3.5-turbo-1106 unless you are specifically trying to break the filter.")
|
704 |
-
return Kijiku.estimate_cost(model, price_case=1)
|
705 |
-
|
706 |
-
elif(model == "gpt-3.5-turbo-1106"):
|
707 |
-
return Kijiku.estimate_cost(model, price_case=2)
|
708 |
-
|
709 |
-
elif(model == "gpt-3.5-turbo-0125"):
|
710 |
-
return Kijiku.estimate_cost(model, price_case=7)
|
711 |
-
|
712 |
-
elif(model == "gpt-3.5-turbo-16k-0613"):
|
713 |
-
print("Warning: gpt-3.5-turbo-16k-0613 is considered depreciated by OpenAI as of November 6, 2023 and could be shutdown as early as June 13, 2024. Consider switching to gpt-3.5-turbo-1106.")
|
714 |
-
return Kijiku.estimate_cost(model, price_case=3)
|
715 |
-
|
716 |
-
elif(model == "gpt-4-1106-preview"):
|
717 |
-
return Kijiku.estimate_cost(model, price_case=4)
|
718 |
-
|
719 |
-
elif(model == "gpt-4-0125-preview"):
|
720 |
-
return Kijiku.estimate_cost(model, price_case=4)
|
721 |
-
|
722 |
-
elif(model == "gpt-4-0314"):
|
723 |
-
print("Warning: gpt-4-0314 is considered depreciated by OpenAI as of June 13, 2023 and could be shutdown as early as June 13, 2024. Consider switching to gpt-4-0613.")
|
724 |
-
return Kijiku.estimate_cost(model, price_case=5)
|
725 |
-
|
726 |
-
elif(model == "gpt-4-0613"):
|
727 |
-
return Kijiku.estimate_cost(model, price_case=5)
|
728 |
-
|
729 |
-
elif(model == "gpt-4-32k-0314"):
|
730 |
-
print("Warning: gpt-4-32k-0314 is considered depreciated by OpenAI as of June 13, 2023 and could be shutdown as early as June 13, 2024. Consider switching to gpt-4-32k-0613.")
|
731 |
-
return Kijiku.estimate_cost(model, price_case=6)
|
732 |
-
|
733 |
-
elif(model == "gpt-4-32k-0613"):
|
734 |
-
return Kijiku.estimate_cost(model, price_case=6)
|
735 |
-
|
736 |
-
elif(model == "gemini-pro"):
|
737 |
-
print(f"Warning: gemini-pro may change over time. Returning num tokens assuming gemini-1.0-pro-001 as it is the most recent version of gemini-1.0-pro.")
|
738 |
-
return Kijiku.estimate_cost("gemini-1.0-pro-001", price_case=8)
|
739 |
-
|
740 |
-
elif(model == "gemini-pro-vision"):
|
741 |
-
print("Warning: gemini-pro-vision may change over time. Returning num tokens assuming gemini-1.0-pro-vision-001 as it is the most recent version of gemini-1.0-pro-vision.")
|
742 |
-
return Kijiku.estimate_cost("gemini-1.0-pro-vision-001", price_case=8)
|
743 |
-
|
744 |
-
elif(model == "gemini-ultra"):
|
745 |
-
return Kijiku.estimate_cost(model, price_case=8)
|
746 |
-
|
747 |
-
elif(model == "gemini-1.0-pro"):
|
748 |
-
print(f"Warning: gemini-1.0-pro may change over time. Returning num tokens assuming gemini-1.0-pro-001 as it is the most recent version of gemini-1.0-pro.")
|
749 |
-
return Kijiku.estimate_cost(model, price_case=8)
|
750 |
-
|
751 |
-
elif(model == "gemini-1.0-pro-vision"):
|
752 |
-
print("Warning: gemini-1.0-pro-vision may change over time. Returning num tokens assuming gemini-1.0-pro-vision-001 as it is the most recent version of gemini-1.0-pro-vision.")
|
753 |
-
return Kijiku.estimate_cost(model, price_case=8)
|
754 |
-
|
755 |
-
elif(model == "gemini-1.0-pro-latest"):
|
756 |
-
print(f"Warning: gemini-1.0-pro-latest may change over time. Returning num tokens assuming gemini-1.0-pro-001 as it is the most recent version of gemini-1.0-pro.")
|
757 |
-
return Kijiku.estimate_cost("gemini-1.0-pro-001", price_case=8)
|
758 |
-
|
759 |
-
elif(model == "gemini-1.0-pro-vision-latest"):
|
760 |
-
print("Warning: gemini-1.0-pro-vision-latest may change over time. Returning num tokens assuming gemini-1.0-pro-vision-001 as it is the most recent version of gemini-1.0-pro-vision.")
|
761 |
-
return Kijiku.estimate_cost("gemini-1.0-pro-vision-001", price_case=8)
|
762 |
-
|
763 |
-
elif(model == "gemini-1.5-pro-latest"):
|
764 |
-
return Kijiku.estimate_cost(model, price_case=8)
|
765 |
-
|
766 |
-
elif(model == "gemini-1.0-ultra-latest"):
|
767 |
-
return Kijiku.estimate_cost(model, price_case=8)
|
768 |
-
|
769 |
-
elif(model == "gemini-1.0-pro-001"):
|
770 |
-
return Kijiku.estimate_cost(model, price_case=8)
|
771 |
-
|
772 |
-
elif(model == "gemini-1.0-pro-vision-001"):
|
773 |
-
return Kijiku.estimate_cost(model, price_case=8)
|
774 |
-
|
775 |
-
else:
|
776 |
-
|
777 |
-
cost_details = MODEL_COSTS.get(model)
|
778 |
-
|
779 |
-
if(not cost_details):
|
780 |
-
raise ValueError(f"Cost details not found for model: {model}.")
|
781 |
-
|
782 |
-
## break down the text into a string than into tokens
|
783 |
-
text = ''.join(Kijiku.text_to_translate)
|
784 |
-
|
785 |
-
if(Kijiku.LLM_TYPE == "openai"):
|
786 |
-
encoding = tiktoken.encoding_for_model(model)
|
787 |
-
num_tokens = len(encoding.encode(text))
|
788 |
-
|
789 |
-
else:
|
790 |
-
num_tokens = GeminiService.count_tokens(text)
|
791 |
-
|
792 |
-
input_cost = cost_details["input_cost"]
|
793 |
-
output_cost = cost_details["output_cost"]
|
794 |
-
|
795 |
-
min_cost_for_input = (num_tokens / 1000) * input_cost
|
796 |
-
min_cost_for_output = (num_tokens / 1000) * output_cost
|
797 |
-
min_cost = min_cost_for_input + min_cost_for_output
|
798 |
-
|
799 |
-
return num_tokens, min_cost, model
|
800 |
-
|
801 |
-
## type checker doesn't like the chance of None being returned, so we raise an exception here if it gets to this point
|
802 |
-
raise Exception("An unknown error occurred while calculating the minimum cost of translation.")
|
803 |
-
|
804 |
##-------------------start-of-handle_cost_estimate_prompt()---------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
805 |
|
806 |
@staticmethod
|
@@ -819,17 +642,19 @@ class Kijiku:
|
|
819 |
|
820 |
"""
|
821 |
|
|
|
|
|
822 |
## get cost estimate and confirm
|
823 |
-
num_tokens, min_cost, model = Kijiku.
|
824 |
|
825 |
-
print("
|
826 |
|
827 |
Logger.log_barrier()
|
828 |
Logger.log_action("Calculating cost")
|
829 |
Logger.log_barrier()
|
830 |
|
831 |
if(Kijiku.LLM_TYPE == "gemini"):
|
832 |
-
Logger.log_action(f"As of Kudasai {Toolkit.CURRENT_VERSION}, Gemini Pro 1.0 is free to use under
|
833 |
|
834 |
Logger.log_action("Estimated number of tokens : " + str(num_tokens), output=True, omit_timestamp=True)
|
835 |
Logger.log_action("Estimated minimum cost : " + str(min_cost) + " USD", output=True, omit_timestamp=True)
|
@@ -849,7 +674,7 @@ class Kijiku:
|
|
849 |
##-------------------start-of-handle_translation()---------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
850 |
|
851 |
@staticmethod
|
852 |
-
async def handle_translation(model:str, index:int, length:int, translation_instructions:typing.Union[str,
|
853 |
|
854 |
"""
|
855 |
|
@@ -885,19 +710,39 @@ class Kijiku:
|
|
885 |
try:
|
886 |
|
887 |
if(Kijiku.LLM_TYPE == "openai"):
|
888 |
-
translated_message = await
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
889 |
|
890 |
else:
|
891 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
892 |
|
893 |
## will only occur if the max_batch_duration is exceeded, so we just return the untranslated text
|
894 |
except MaxBatchDurationExceededException:
|
895 |
-
|
896 |
Logger.log_error(f"Batch {message_number} of {length//2} was not translated due to exceeding the max request duration, returning the untranslated text...", output=True)
|
897 |
break
|
898 |
|
899 |
## do not even bother if not a gpt 4 model, because gpt-3 seems unable to format properly
|
900 |
-
if
|
|
|
901 |
break
|
902 |
|
903 |
if(await Kijiku.check_if_translation_is_good(translated_message, translation_prompt)):
|
@@ -913,12 +758,18 @@ class Kijiku:
|
|
913 |
Logger.log_error(f"Batch {message_number} of {length//2} was malformed, retrying...", output=True)
|
914 |
Kijiku.num_occurred_malformed_batches += 1
|
915 |
|
|
|
|
|
|
|
|
|
|
|
|
|
916 |
return index, translation_prompt, translated_message
|
917 |
|
918 |
##-------------------start-of-check_if_translation_is_good()---------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
919 |
|
920 |
@staticmethod
|
921 |
-
async def check_if_translation_is_good(translated_message:str, translation_prompt:typing.Union[
|
922 |
|
923 |
"""
|
924 |
|
@@ -938,6 +789,9 @@ class Kijiku:
|
|
938 |
|
939 |
else:
|
940 |
prompt = translation_prompt
|
|
|
|
|
|
|
941 |
|
942 |
is_valid = False
|
943 |
|
|
|
9 |
|
10 |
## third party modules
|
11 |
from kairyou import KatakanaUtil
|
12 |
+
from easytl import EasyTL, Message, SystemTranslationMessage, ModelTranslationMessage
|
13 |
|
|
|
14 |
import backoff
|
15 |
|
16 |
## custom modules
|
|
|
22 |
from modules.common.exceptions import AuthenticationError, MaxBatchDurationExceededException, AuthenticationError, InternalServerError, RateLimitError, APITimeoutError, GoogleAuthError
|
23 |
from modules.common.decorators import permission_error_decorator
|
24 |
|
|
|
|
|
|
|
|
|
|
|
25 |
##-------------------start-of-Kijiku--------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
26 |
|
27 |
class Kijiku:
|
|
|
43 |
|
44 |
## the messages that will be sent to the api, contains a system message and a model message, system message is the instructions,
|
45 |
## model message is the text that will be translated
|
46 |
+
openai_translation_batches:typing.List[SystemTranslationMessage | ModelTranslationMessage] = []
|
47 |
|
48 |
## meanwhile for gemini, we just need to send the prompt and the text to be translated concatenated together
|
49 |
gemini_translation_batches:typing.List[str] = []
|
|
|
69 |
batch_retry_timeout:float
|
70 |
num_concurrent_batches:int
|
71 |
|
72 |
+
decorator_to_use:typing.Callable
|
73 |
+
|
74 |
##-------------------start-of-get_max_batch_duration()---------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
75 |
|
76 |
@staticmethod
|
|
|
193 |
Toolkit.clear_console()
|
194 |
|
195 |
if(Kijiku.LLM_TYPE == "openai"):
|
196 |
+
await Kijiku.init_api_key("OpenAI", FileEnsurer.openai_api_key_path, EasyTL.set_api_key, EasyTL.test_api_key_validity)
|
197 |
|
198 |
else:
|
199 |
+
await Kijiku.init_api_key("Gemini", FileEnsurer.gemini_api_key_path, EasyTL.set_api_key, EasyTL.test_api_key_validity)
|
200 |
|
201 |
## try to load the kijiku rules
|
202 |
try:
|
|
|
229 |
|
230 |
"""
|
231 |
|
|
|
|
|
|
|
232 |
## get saved API key if exists
|
233 |
try:
|
234 |
with open(api_key_path, 'r', encoding='utf-8') as file:
|
235 |
api_key = base64.b64decode((file.read()).encode('utf-8')).decode('utf-8')
|
236 |
|
237 |
+
api_key_setter(service.lower(), api_key)
|
238 |
|
239 |
+
is_valid, e = api_key_tester(service.lower())
|
240 |
|
241 |
## if not valid, raise the exception that caused the test to fail
|
242 |
if(not is_valid and e is not None):
|
|
|
257 |
## if valid save the API key
|
258 |
try:
|
259 |
|
260 |
+
api_key_setter(service.lower(), api_key)
|
261 |
|
262 |
+
is_valid, e = api_key_tester(service.lower())
|
263 |
|
264 |
if(not is_valid and e is not None):
|
265 |
raise e
|
|
|
359 |
if(os.path.exists(FileEnsurer.openai_api_key_path)):
|
360 |
|
361 |
os.remove(FileEnsurer.openai_api_key_path)
|
362 |
+
await Kijiku.init_api_key("OpenAI", FileEnsurer.openai_api_key_path, EasyTL.set_api_key, EasyTL.test_api_key_validity)
|
363 |
|
364 |
else:
|
365 |
|
366 |
if(os.path.exists(FileEnsurer.gemini_api_key_path)):
|
367 |
|
368 |
os.remove(FileEnsurer.gemini_api_key_path)
|
369 |
+
await Kijiku.init_api_key("Gemini", FileEnsurer.gemini_api_key_path, EasyTL.set_api_key, EasyTL.test_api_key_validity)
|
370 |
|
371 |
Toolkit.clear_console()
|
372 |
|
|
|
403 |
|
404 |
Kijiku._semaphore = asyncio.Semaphore(Kijiku.num_concurrent_batches)
|
405 |
|
406 |
+
Kijiku.openai_model = JsonHandler.current_kijiku_rules["openai settings"]["openai_model"]
|
407 |
+
Kijiku.openai_system_message = JsonHandler.current_kijiku_rules["openai settings"]["openai_system_message"]
|
408 |
+
Kijiku.openai_temperature = float(JsonHandler.current_kijiku_rules["openai settings"]["openai_temperature"])
|
409 |
+
Kijiku.openai_top_p = float(JsonHandler.current_kijiku_rules["openai settings"]["openai_top_p"])
|
410 |
+
Kijiku.openai_n = int(JsonHandler.current_kijiku_rules["openai settings"]["openai_n"])
|
411 |
+
Kijiku.openai_stream = bool(JsonHandler.current_kijiku_rules["openai settings"]["openai_stream"])
|
412 |
+
Kijiku.openai_stop = JsonHandler.current_kijiku_rules["openai settings"]["openai_stop"]
|
413 |
+
Kijiku.openai_logit_bias = JsonHandler.current_kijiku_rules["openai settings"]["openai_logit_bias"]
|
414 |
+
Kijiku.openai_max_tokens = JsonHandler.current_kijiku_rules["openai settings"]["openai_max_tokens"]
|
415 |
+
Kijiku.openai_presence_penalty = float(JsonHandler.current_kijiku_rules["openai settings"]["openai_presence_penalty"])
|
416 |
+
Kijiku.openai_frequency_penalty = float(JsonHandler.current_kijiku_rules["openai settings"]["openai_frequency_penalty"])
|
417 |
+
|
418 |
+
Kijiku.gemini_model = JsonHandler.current_kijiku_rules["gemini settings"]["gemini_model"]
|
419 |
+
Kijiku.gemini_prompt = JsonHandler.current_kijiku_rules["gemini settings"]["gemini_prompt"]
|
420 |
+
Kijiku.gemini_temperature = float(JsonHandler.current_kijiku_rules["gemini settings"]["gemini_temperature"])
|
421 |
+
Kijiku.gemini_top_p = JsonHandler.current_kijiku_rules["gemini settings"]["gemini_top_p"]
|
422 |
+
Kijiku.gemini_top_k = JsonHandler.current_kijiku_rules["gemini settings"]["gemini_top_k"]
|
423 |
+
Kijiku.gemini_candidate_count = JsonHandler.current_kijiku_rules["gemini settings"]["gemini_candidate_count"]
|
424 |
+
Kijiku.gemini_stream = bool(JsonHandler.current_kijiku_rules["gemini settings"]["gemini_stream"])
|
425 |
+
Kijiku.gemini_stop_sequences = JsonHandler.current_kijiku_rules["gemini settings"]["gemini_stop_sequences"]
|
426 |
+
Kijiku.gemini_max_output_tokens = JsonHandler.current_kijiku_rules["gemini settings"]["gemini_max_output_tokens"]
|
427 |
|
|
|
428 |
|
429 |
+
if(Kijiku.LLM_TYPE == "openai"):
|
430 |
+
Kijiku.decorator_to_use = backoff.on_exception(backoff.expo, max_time=lambda: Kijiku.get_max_batch_duration(), exception=(AuthenticationError, InternalServerError, RateLimitError, APITimeoutError), on_backoff=lambda details: Kijiku.log_retry(details), on_giveup=lambda details: Kijiku.log_failure(details), raise_on_giveup=False)
|
|
|
|
|
431 |
|
432 |
else:
|
433 |
+
Kijiku.decorator_to_use = backoff.on_exception(backoff.expo, max_time=lambda: Kijiku.get_max_batch_duration(), exception=(Exception), on_backoff=lambda details: Kijiku.log_retry(details), on_giveup=lambda details: Kijiku.log_failure(details), raise_on_giveup=False)
|
|
|
|
|
|
|
|
|
434 |
|
435 |
Toolkit.clear_console()
|
436 |
|
|
|
440 |
|
441 |
Kijiku.build_translation_batches()
|
442 |
|
443 |
+
model = JsonHandler.current_kijiku_rules["openai settings"]["openai_model"] if Kijiku.LLM_TYPE == "openai" else JsonHandler.current_kijiku_rules["gemini settings"]["gemini_model"]
|
444 |
|
445 |
await Kijiku.handle_cost_estimate_prompt(model, omit_prompt=is_webgui)
|
446 |
|
|
|
506 |
translation_batches = Kijiku.openai_translation_batches if Kijiku.LLM_TYPE == "openai" else Kijiku.gemini_translation_batches
|
507 |
|
508 |
for i in range(0, len(translation_batches), 2):
|
509 |
+
|
510 |
+
instructions = translation_batches[i]
|
511 |
+
prompt = translation_batches[i+1]
|
512 |
+
|
513 |
+
assert isinstance(instructions, SystemTranslationMessage) or isinstance(instructions, str)
|
514 |
+
assert isinstance(prompt, ModelTranslationMessage) or isinstance(prompt, str)
|
515 |
+
|
516 |
+
async_requests.append(Kijiku.handle_translation(model, i, len(translation_batches), instructions, prompt))
|
517 |
|
518 |
return async_requests
|
519 |
|
|
|
595 |
if(Kijiku.LLM_TYPE == 'openai'):
|
596 |
|
597 |
if(Kijiku.prompt_assembly_mode == 1):
|
598 |
+
system_msg = SystemTranslationMessage(content=str(Kijiku.openai_system_message))
|
599 |
else:
|
600 |
+
system_msg = SystemTranslationMessage(content=str(Kijiku.openai_system_message))
|
601 |
|
602 |
Kijiku.openai_translation_batches.append(system_msg)
|
603 |
model_msg = ModelTranslationMessage(content=batch)
|
604 |
Kijiku.openai_translation_batches.append(model_msg)
|
605 |
|
606 |
else:
|
607 |
+
Kijiku.gemini_translation_batches.append(Kijiku.gemini_prompt)
|
608 |
Kijiku.gemini_translation_batches.append(batch)
|
609 |
|
610 |
Logger.log_barrier()
|
|
|
624 |
|
625 |
Logger.log_action(message)
|
626 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
627 |
##-------------------start-of-handle_cost_estimate_prompt()---------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
628 |
|
629 |
@staticmethod
|
|
|
642 |
|
643 |
"""
|
644 |
|
645 |
+
translation_instructions = Kijiku.openai_system_message if Kijiku.LLM_TYPE == "openai" else Kijiku.gemini_prompt
|
646 |
+
|
647 |
## get cost estimate and confirm
|
648 |
+
num_tokens, min_cost, model = EasyTL.calculate_cost(text=Kijiku.text_to_translate, service=Kijiku.LLM_TYPE, model=model,translation_instructions=translation_instructions)
|
649 |
|
650 |
+
print("Note that the cost estimate is not always accurate, and may be higher than the actual cost. However cost calculation now includes output tokens.\n")
|
651 |
|
652 |
Logger.log_barrier()
|
653 |
Logger.log_action("Calculating cost")
|
654 |
Logger.log_barrier()
|
655 |
|
656 |
if(Kijiku.LLM_TYPE == "gemini"):
|
657 |
+
Logger.log_action(f"As of Kudasai {Toolkit.CURRENT_VERSION}, Gemini Pro 1.0 is free to use under 15 requests per minute, Gemini Pro 1.5 is free to use under 2 requests per minute. Requests correspond to number_of_current_batches in kijiku_settings.", output=True, omit_timestamp=True)
|
658 |
|
659 |
Logger.log_action("Estimated number of tokens : " + str(num_tokens), output=True, omit_timestamp=True)
|
660 |
Logger.log_action("Estimated minimum cost : " + str(min_cost) + " USD", output=True, omit_timestamp=True)
|
|
|
674 |
##-------------------start-of-handle_translation()---------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
675 |
|
676 |
@staticmethod
|
677 |
+
async def handle_translation(model:str, index:int, length:int, translation_instructions:typing.Union[str, SystemTranslationMessage], translation_prompt:typing.Union[str, ModelTranslationMessage]) -> tuple[int, str, str]:
|
678 |
|
679 |
"""
|
680 |
|
|
|
710 |
try:
|
711 |
|
712 |
if(Kijiku.LLM_TYPE == "openai"):
|
713 |
+
translated_message = await EasyTL.openai_translate_async(text=translation_prompt,
|
714 |
+
decorator=Kijiku.decorator_to_use,
|
715 |
+
translation_instructions=translation_instructions,
|
716 |
+
model=model,
|
717 |
+
temperature=Kijiku.openai_temperature,
|
718 |
+
top_p=Kijiku.openai_top_p,
|
719 |
+
stop=Kijiku.openai_stop,
|
720 |
+
max_tokens=Kijiku.openai_max_tokens,
|
721 |
+
presence_penalty=Kijiku.openai_presence_penalty,
|
722 |
+
frequency_penalty=Kijiku.openai_frequency_penalty)
|
723 |
|
724 |
else:
|
725 |
+
|
726 |
+
assert isinstance(translation_prompt, str)
|
727 |
+
|
728 |
+
translated_message = await EasyTL.gemini_translate_async(text=translation_prompt,
|
729 |
+
decorator=Kijiku.decorator_to_use,
|
730 |
+
model=model,
|
731 |
+
temperature=Kijiku.gemini_temperature,
|
732 |
+
top_p=Kijiku.gemini_top_p,
|
733 |
+
top_k=Kijiku.gemini_top_k,
|
734 |
+
stop_sequences=Kijiku.gemini_stop_sequences,
|
735 |
+
max_output_tokens=Kijiku.gemini_max_output_tokens)
|
736 |
|
737 |
## will only occur if the max_batch_duration is exceeded, so we just return the untranslated text
|
738 |
except MaxBatchDurationExceededException:
|
739 |
+
|
740 |
Logger.log_error(f"Batch {message_number} of {length//2} was not translated due to exceeding the max request duration, returning the untranslated text...", output=True)
|
741 |
break
|
742 |
|
743 |
## do not even bother if not a gpt 4 model, because gpt-3 seems unable to format properly
|
744 |
+
## since gemini is free, we can just try again if it's malformed
|
745 |
+
if("gpt-4" not in model and Kijiku.LLM_TYPE != "gemini"):
|
746 |
break
|
747 |
|
748 |
if(await Kijiku.check_if_translation_is_good(translated_message, translation_prompt)):
|
|
|
758 |
Logger.log_error(f"Batch {message_number} of {length//2} was malformed, retrying...", output=True)
|
759 |
Kijiku.num_occurred_malformed_batches += 1
|
760 |
|
761 |
+
if(isinstance(translation_prompt, ModelTranslationMessage)):
|
762 |
+
translation_prompt = translation_prompt.content
|
763 |
+
|
764 |
+
if(isinstance(translated_message, typing.List)):
|
765 |
+
translated_message = ''.join(translated_message)
|
766 |
+
|
767 |
return index, translation_prompt, translated_message
|
768 |
|
769 |
##-------------------start-of-check_if_translation_is_good()---------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
770 |
|
771 |
@staticmethod
|
772 |
+
async def check_if_translation_is_good(translated_message:typing.Union[typing.List[str], str], translation_prompt:typing.Union[ModelTranslationMessage, str]) -> bool:
|
773 |
|
774 |
"""
|
775 |
|
|
|
789 |
|
790 |
else:
|
791 |
prompt = translation_prompt
|
792 |
+
|
793 |
+
if(isinstance(translated_message, list)):
|
794 |
+
translated_message = ''.join(translated_message)
|
795 |
|
796 |
is_valid = False
|
797 |
|
modules/common/exceptions.py
CHANGED
@@ -1,9 +1,8 @@
|
|
1 |
## third-party libraries
|
2 |
-
|
3 |
## for importing, other scripts will use from common.exceptions instead of from the third-party libraries themselves
|
4 |
-
from
|
5 |
-
from
|
6 |
-
from
|
7 |
|
8 |
##-------------------start-of-MaxBatchDurationExceededException--------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
9 |
|
@@ -15,7 +14,16 @@ class MaxBatchDurationExceededException(Exception):
|
|
15 |
|
16 |
"""
|
17 |
|
18 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
19 |
|
20 |
##-------------------start-of-InvalidAPIKeyException--------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
21 |
|
|
|
1 |
## third-party libraries
|
|
|
2 |
## for importing, other scripts will use from common.exceptions instead of from the third-party libraries themselves
|
3 |
+
from easytl import AuthenticationError, InternalServerError, RateLimitError, APITimeoutError
|
4 |
+
from easytl import AuthorizationException, QuotaExceededException
|
5 |
+
from easytl import GoogleAuthError
|
6 |
|
7 |
##-------------------start-of-MaxBatchDurationExceededException--------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
8 |
|
|
|
14 |
|
15 |
"""
|
16 |
|
17 |
+
def __init__(self, message:str) -> None:
|
18 |
+
|
19 |
+
"""
|
20 |
+
|
21 |
+
Parameters:
|
22 |
+
message (string) : The message to display.
|
23 |
+
|
24 |
+
"""
|
25 |
+
|
26 |
+
self.message = message
|
27 |
|
28 |
##-------------------start-of-InvalidAPIKeyException--------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
29 |
|
modules/common/file_ensurer.py
CHANGED
@@ -105,39 +105,6 @@ class FileEnsurer():
|
|
105 |
"gemini_max_output_tokens": None
|
106 |
}
|
107 |
}
|
108 |
-
|
109 |
-
|
110 |
-
ALLOWED_OPENAI_MODELS = [
|
111 |
-
"gpt-3.5-turbo",
|
112 |
-
"gpt-4",
|
113 |
-
"gpt-4-turbo-preview",
|
114 |
-
"gpt-3.5-turbo-0301",
|
115 |
-
"gpt-4-0314",
|
116 |
-
"gpt-4-32k-0314",
|
117 |
-
"gpt-3.5-turbo-0613",
|
118 |
-
"gpt-3.5-turbo-0125",
|
119 |
-
"gpt-3.5-turbo-16k-0613",
|
120 |
-
"gpt-3.5-turbo-1106",
|
121 |
-
"gpt-4-0613",
|
122 |
-
"gpt-4-32k-0613",
|
123 |
-
"gpt-4-1106-preview",
|
124 |
-
"gpt-4-0125-preview"
|
125 |
-
]
|
126 |
-
|
127 |
-
ALLOWED_GEMINI_MODELS = [
|
128 |
-
"gemini-1.0-pro-001",
|
129 |
-
"gemini-1.0-pro-vision-001",
|
130 |
-
"gemini-1.0-pro",
|
131 |
-
"gemini-1.0-pro-vision",
|
132 |
-
"gemini-1.0-pro-latest",
|
133 |
-
"gemini-1.0-pro-vision-latest",
|
134 |
-
"gemini-1.5-pro-latest",
|
135 |
-
"gemini-1.0-ultra-latest",
|
136 |
-
"gemini-pro",
|
137 |
-
"gemini-pro-vision",
|
138 |
-
"gemini-ultra"
|
139 |
-
]
|
140 |
-
|
141 |
INVALID_KIJIKU_RULES_PLACEHOLDER = {
|
142 |
"INVALID JSON":
|
143 |
{
|
@@ -262,6 +229,7 @@ class FileEnsurer():
|
|
262 |
else:
|
263 |
with open(thing, "w", encoding="utf-8") as file:
|
264 |
file.truncate()
|
|
|
265 |
##--------------------start-of-standard_create_directory()------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
266 |
|
267 |
@staticmethod
|
|
|
105 |
"gemini_max_output_tokens": None
|
106 |
}
|
107 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
108 |
INVALID_KIJIKU_RULES_PLACEHOLDER = {
|
109 |
"INVALID JSON":
|
110 |
{
|
|
|
229 |
else:
|
230 |
with open(thing, "w", encoding="utf-8") as file:
|
231 |
file.truncate()
|
232 |
+
|
233 |
##--------------------start-of-standard_create_directory()------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
234 |
|
235 |
@staticmethod
|
modules/common/toolkit.py
CHANGED
@@ -14,7 +14,7 @@ class Toolkit():
|
|
14 |
|
15 |
"""
|
16 |
|
17 |
-
CURRENT_VERSION = "v3.4.
|
18 |
|
19 |
##-------------------start-of-clear_console()---------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
20 |
|
|
|
14 |
|
15 |
"""
|
16 |
|
17 |
+
CURRENT_VERSION = "v3.4.3"
|
18 |
|
19 |
##-------------------start-of-clear_console()---------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
20 |
|
requirements.txt
CHANGED
@@ -1,8 +1,5 @@
|
|
1 |
-
deepl==1.16.1
|
2 |
-
openai==1.13.3
|
3 |
backoff==2.2.1
|
4 |
-
tiktoken==0.6.0
|
5 |
gradio==4.19.2
|
6 |
kairyou==1.4.1
|
7 |
-
|
8 |
ja_core_news_lg @ https://github.com/explosion/spacy-models/releases/download/ja_core_news_lg-3.7.0/ja_core_news_lg-3.7.0-py3-none-any.whl#sha256=f08eecb4d40523045c9478ce59a67564fd71edd215f32c076fa91dc1f05cc7fd
|
|
|
|
|
|
|
1 |
backoff==2.2.1
|
|
|
2 |
gradio==4.19.2
|
3 |
kairyou==1.4.1
|
4 |
+
easytl==0.1.0
|
5 |
ja_core_news_lg @ https://github.com/explosion/spacy-models/releases/download/ja_core_news_lg-3.7.0/ja_core_news_lg-3.7.0-py3-none-any.whl#sha256=f08eecb4d40523045c9478ce59a67564fd71edd215f32c076fa91dc1f05cc7fd
|
translation_services/deepl_service.py
DELETED
@@ -1,85 +0,0 @@
|
|
1 |
-
## built-in libraries
|
2 |
-
import typing
|
3 |
-
|
4 |
-
## third-party libraries
|
5 |
-
from deepl.translator import Translator
|
6 |
-
|
7 |
-
class DeepLService:
|
8 |
-
|
9 |
-
api_key:str
|
10 |
-
translator:Translator
|
11 |
-
|
12 |
-
##-------------------start-of-translate()---------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
13 |
-
|
14 |
-
@staticmethod
|
15 |
-
def translate(text:str, target_lang:str, source_lang:str) -> str:
|
16 |
-
|
17 |
-
"""
|
18 |
-
|
19 |
-
Translates the text to the target language.
|
20 |
-
|
21 |
-
Parameters:
|
22 |
-
text (string) : The text to translate.
|
23 |
-
target_lang (string) : The target language.
|
24 |
-
source_lang (string) : The source language.
|
25 |
-
|
26 |
-
Returns:
|
27 |
-
translation (string) : The translated text.
|
28 |
-
|
29 |
-
"""
|
30 |
-
|
31 |
-
try:
|
32 |
-
|
33 |
-
translation = DeepLService.translator.translate_text(text, target_lang=target_lang, source_lang=source_lang)
|
34 |
-
|
35 |
-
return str(translation)
|
36 |
-
|
37 |
-
except Exception as e:
|
38 |
-
raise e
|
39 |
-
|
40 |
-
##-------------------start-of-set_api_key()---------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
41 |
-
|
42 |
-
@staticmethod
|
43 |
-
def set_api_key(api_key:str) -> None:
|
44 |
-
|
45 |
-
"""
|
46 |
-
|
47 |
-
Sets the API key for the DeepL client.
|
48 |
-
|
49 |
-
Parameters:
|
50 |
-
api_key (string) : The API key to set.
|
51 |
-
|
52 |
-
"""
|
53 |
-
|
54 |
-
DeepLService.api_key = api_key
|
55 |
-
|
56 |
-
##-------------------start-of-test_api_key_validity()---------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
57 |
-
|
58 |
-
@staticmethod
|
59 |
-
def test_api_key_validity() -> typing.Tuple[bool, typing.Union[Exception, None]]:
|
60 |
-
|
61 |
-
"""
|
62 |
-
|
63 |
-
Tests the validity of the API key.
|
64 |
-
|
65 |
-
Returns:
|
66 |
-
validity (bool) : True if the API key is valid, False if it is not.
|
67 |
-
e (Exception) : The exception that was raised, if any.
|
68 |
-
|
69 |
-
"""
|
70 |
-
|
71 |
-
validity = False
|
72 |
-
|
73 |
-
try:
|
74 |
-
|
75 |
-
DeepLService.translator = Translator(DeepLService.api_key)
|
76 |
-
|
77 |
-
DeepLService.translator.translate_text("test", target_lang="JA")
|
78 |
-
|
79 |
-
validity = True
|
80 |
-
|
81 |
-
return validity, None
|
82 |
-
|
83 |
-
except Exception as e:
|
84 |
-
|
85 |
-
return validity, e
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
translation_services/gemini_service.py
DELETED
@@ -1,215 +0,0 @@
|
|
1 |
-
## built-in libraries
|
2 |
-
import typing
|
3 |
-
|
4 |
-
## third party libraries
|
5 |
-
from google.generativeai import GenerationConfig
|
6 |
-
import google.generativeai as genai
|
7 |
-
|
8 |
-
class GeminiService:
|
9 |
-
|
10 |
-
model:str = "gemini-pro"
|
11 |
-
prompt:str = ""
|
12 |
-
temperature:float = 0.5
|
13 |
-
top_p:float = 0.9
|
14 |
-
top_k:int = 40
|
15 |
-
candidate_count:int = 1
|
16 |
-
stream:bool = False
|
17 |
-
stop_sequences:typing.List[str] | None = None
|
18 |
-
max_output_tokens:int | None = None
|
19 |
-
|
20 |
-
client:genai.GenerativeModel
|
21 |
-
generation_config:GenerationConfig
|
22 |
-
|
23 |
-
decorator_to_use:typing.Union[typing.Callable, None] = None
|
24 |
-
|
25 |
-
safety_settings = [
|
26 |
-
{
|
27 |
-
"category": "HARM_CATEGORY_DANGEROUS",
|
28 |
-
"threshold": "BLOCK_NONE",
|
29 |
-
},
|
30 |
-
{
|
31 |
-
"category": "HARM_CATEGORY_HARASSMENT",
|
32 |
-
"threshold": "BLOCK_NONE",
|
33 |
-
},
|
34 |
-
{
|
35 |
-
"category": "HARM_CATEGORY_HATE_SPEECH",
|
36 |
-
"threshold": "BLOCK_NONE",
|
37 |
-
},
|
38 |
-
{
|
39 |
-
"category": "HARM_CATEGORY_SEXUALLY_EXPLICIT",
|
40 |
-
"threshold": "BLOCK_NONE",
|
41 |
-
},
|
42 |
-
{
|
43 |
-
"category": "HARM_CATEGORY_DANGEROUS_CONTENT",
|
44 |
-
"threshold": "BLOCK_NONE",
|
45 |
-
},
|
46 |
-
]
|
47 |
-
|
48 |
-
##-------------------start-of-set_api_key()---------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
49 |
-
|
50 |
-
@staticmethod
|
51 |
-
def set_api_key(api_key:str) -> None:
|
52 |
-
|
53 |
-
"""
|
54 |
-
|
55 |
-
Sets the API key for the Gemini client.
|
56 |
-
|
57 |
-
Parameters:
|
58 |
-
api_key (string) : The API key to set.
|
59 |
-
|
60 |
-
"""
|
61 |
-
|
62 |
-
genai.configure(api_key=api_key)
|
63 |
-
|
64 |
-
##-------------------start-of-set_decorator()---------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
65 |
-
|
66 |
-
@staticmethod
|
67 |
-
def set_decorator(decorator:typing.Callable) -> None:
|
68 |
-
|
69 |
-
"""
|
70 |
-
|
71 |
-
Sets the decorator to use for the Gemini service. Should be a callable that returns a decorator.
|
72 |
-
|
73 |
-
Parameters:
|
74 |
-
decorator (callable) : The decorator to use.
|
75 |
-
|
76 |
-
"""
|
77 |
-
|
78 |
-
GeminiService.decorator_to_use = decorator
|
79 |
-
|
80 |
-
##-------------------start-of-setup_client()---------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
81 |
-
|
82 |
-
@staticmethod
|
83 |
-
def redefine_client() -> None:
|
84 |
-
|
85 |
-
"""
|
86 |
-
|
87 |
-
Redefines the Gemini client and generation config. This should be called before making any requests to the Gemini service, or after changing any of the service's settings.
|
88 |
-
|
89 |
-
"""
|
90 |
-
|
91 |
-
GeminiService.client = genai.GenerativeModel(GeminiService.model)
|
92 |
-
GeminiService.generation_config = GenerationConfig(candidate_count=GeminiService.candidate_count,
|
93 |
-
max_output_tokens=GeminiService.max_output_tokens,
|
94 |
-
stop_sequences=GeminiService.stop_sequences,
|
95 |
-
temperature=GeminiService.temperature,
|
96 |
-
top_p=GeminiService.top_p,
|
97 |
-
top_k=GeminiService.top_k)
|
98 |
-
|
99 |
-
##-------------------start-of-count_tokens()---------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
100 |
-
|
101 |
-
@staticmethod
|
102 |
-
def count_tokens(prompt:str) -> int:
|
103 |
-
|
104 |
-
"""
|
105 |
-
|
106 |
-
Counts the number of tokens in a prompt.
|
107 |
-
|
108 |
-
Parameters:
|
109 |
-
prompt (string) : The prompt to count the tokens of.
|
110 |
-
|
111 |
-
Returns:
|
112 |
-
count (int) : The number of tokens in the prompt.
|
113 |
-
|
114 |
-
"""
|
115 |
-
|
116 |
-
return genai.GenerativeModel(GeminiService.model).count_tokens(prompt).total_tokens
|
117 |
-
|
118 |
-
##-------------------start-of-trans()---------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
119 |
-
|
120 |
-
@staticmethod
|
121 |
-
async def translate_message(translation_instructions:str, translation_prompt:str) -> str:
|
122 |
-
|
123 |
-
"""
|
124 |
-
|
125 |
-
Translates a prompt.
|
126 |
-
|
127 |
-
Parameters:
|
128 |
-
translation_prompt (object - ModelTranslationMessage) : The prompt to translate.
|
129 |
-
|
130 |
-
Returns:
|
131 |
-
output (string) : The translation.
|
132 |
-
|
133 |
-
"""
|
134 |
-
|
135 |
-
if(GeminiService.decorator_to_use is None):
|
136 |
-
return await GeminiService._translate_message(translation_instructions, translation_prompt)
|
137 |
-
|
138 |
-
decorated_function = GeminiService.decorator_to_use(GeminiService._translate_message)
|
139 |
-
return await decorated_function(translation_instructions, translation_prompt)
|
140 |
-
|
141 |
-
##-------------------start-of-_translate_message()---------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
142 |
-
|
143 |
-
@staticmethod
|
144 |
-
async def _translate_message(translation_instructions:str, translation_prompt:str) -> str:
|
145 |
-
|
146 |
-
"""
|
147 |
-
|
148 |
-
Translates a prompt.
|
149 |
-
|
150 |
-
Parameters:
|
151 |
-
translation_prompt (string) : The prompt to translate.
|
152 |
-
|
153 |
-
Returns:
|
154 |
-
output (string) a string that gpt gives to us also known as the translation.
|
155 |
-
|
156 |
-
"""
|
157 |
-
|
158 |
-
response = await GeminiService.client.generate_content_async(
|
159 |
-
contents=translation_instructions + "\n" + translation_prompt,
|
160 |
-
generation_config=GeminiService.generation_config,
|
161 |
-
safety_settings=GeminiService.safety_settings,
|
162 |
-
stream=GeminiService.stream
|
163 |
-
)
|
164 |
-
|
165 |
-
return response.text
|
166 |
-
|
167 |
-
##-------------------start-of-test_api_key_validity()---------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
168 |
-
|
169 |
-
@staticmethod
|
170 |
-
async def test_api_key_validity() -> typing.Tuple[bool, typing.Union[Exception, None]]:
|
171 |
-
|
172 |
-
"""
|
173 |
-
|
174 |
-
Tests the validity of the API key.
|
175 |
-
|
176 |
-
Returns:
|
177 |
-
validity (bool) : True if the API key is valid, False if it is not.
|
178 |
-
e (Exception) : The exception that was raised, if any.
|
179 |
-
|
180 |
-
"""
|
181 |
-
|
182 |
-
validity = False
|
183 |
-
|
184 |
-
try:
|
185 |
-
|
186 |
-
generation_config = GenerationConfig(candidate_count=1, max_output_tokens=1)
|
187 |
-
|
188 |
-
await GeminiService.client.generate_content_async(
|
189 |
-
"Respond to this prompt with 1",generation_config=generation_config
|
190 |
-
|
191 |
-
)
|
192 |
-
|
193 |
-
validity = True
|
194 |
-
|
195 |
-
return validity, None
|
196 |
-
|
197 |
-
except Exception as e:
|
198 |
-
|
199 |
-
return validity, e
|
200 |
-
|
201 |
-
##-------------------start-of-get_decorator()---------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
202 |
-
|
203 |
-
@staticmethod
|
204 |
-
def get_decorator() -> typing.Union[typing.Callable, None]:
|
205 |
-
|
206 |
-
"""
|
207 |
-
|
208 |
-
Returns the decorator to use for the Gemini service.
|
209 |
-
|
210 |
-
Returns:
|
211 |
-
decorator (callable) : The decorator to use.
|
212 |
-
|
213 |
-
"""
|
214 |
-
|
215 |
-
return GeminiService.decorator_to_use
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
translation_services/openai_service.py
DELETED
@@ -1,180 +0,0 @@
|
|
1 |
-
## built-in libraries
|
2 |
-
import typing
|
3 |
-
|
4 |
-
## third-party libraries
|
5 |
-
from openai import AsyncOpenAI
|
6 |
-
|
7 |
-
## custom modules
|
8 |
-
from modules.common.exceptions import InvalidAPIKeyException
|
9 |
-
from custom_classes.messages import SystemTranslationMessage, Message
|
10 |
-
|
11 |
-
class OpenAIService:
|
12 |
-
|
13 |
-
## async client session
|
14 |
-
client = AsyncOpenAI(max_retries=0, api_key="DummyKey")
|
15 |
-
|
16 |
-
model:str
|
17 |
-
system_message:typing.Optional[typing.Union[SystemTranslationMessage, str]] = None
|
18 |
-
temperature:float
|
19 |
-
top_p:float
|
20 |
-
n:int
|
21 |
-
stream:bool
|
22 |
-
stop:typing.List[str] | None
|
23 |
-
logit_bias:typing.Dict[str, float] | None
|
24 |
-
max_tokens:int | None
|
25 |
-
presence_penalty:float
|
26 |
-
frequency_penalty:float
|
27 |
-
|
28 |
-
decorator_to_use:typing.Union[typing.Callable, None] = None
|
29 |
-
|
30 |
-
##-------------------start-of-set_api_key()---------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
31 |
-
|
32 |
-
@staticmethod
|
33 |
-
def set_api_key(api_key:str) -> None:
|
34 |
-
|
35 |
-
"""
|
36 |
-
|
37 |
-
Sets the API key for the OpenAI client.
|
38 |
-
|
39 |
-
Parameters:
|
40 |
-
api_key (string) : The API key to set.
|
41 |
-
|
42 |
-
"""
|
43 |
-
|
44 |
-
OpenAIService.client.api_key = api_key
|
45 |
-
|
46 |
-
##-------------------start-of-set_decorator()---------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
47 |
-
|
48 |
-
@staticmethod
|
49 |
-
def set_decorator(decorator:typing.Callable) -> None:
|
50 |
-
|
51 |
-
"""
|
52 |
-
|
53 |
-
Sets the decorator to use for the OpenAI service. Should be a callable that returns a decorator.
|
54 |
-
|
55 |
-
Parameters:
|
56 |
-
decorator (callable) : The decorator to use.
|
57 |
-
|
58 |
-
"""
|
59 |
-
|
60 |
-
OpenAIService.decorator_to_use = decorator
|
61 |
-
|
62 |
-
##-------------------start-of-trans()---------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
63 |
-
|
64 |
-
@staticmethod
|
65 |
-
async def translate_message(translation_instructions:Message, translation_prompt:Message) -> str:
|
66 |
-
|
67 |
-
"""
|
68 |
-
|
69 |
-
Translates a system and user message.
|
70 |
-
|
71 |
-
Parameters:
|
72 |
-
translation_instructions (object - SystemTranslationMessage | ModelTranslationMessage) : The system message also known as the instructions.
|
73 |
-
translation_prompt (object - ModelTranslationMessage) : The user message also known as the prompt.
|
74 |
-
|
75 |
-
Returns:
|
76 |
-
output (string) a string that gpt gives to us also known as the translation.
|
77 |
-
|
78 |
-
"""
|
79 |
-
|
80 |
-
if(OpenAIService.decorator_to_use == None):
|
81 |
-
return await OpenAIService._translate_message(translation_instructions, translation_prompt)
|
82 |
-
|
83 |
-
decorated_function = OpenAIService.decorator_to_use(OpenAIService._translate_message)
|
84 |
-
return await decorated_function(translation_instructions, translation_prompt)
|
85 |
-
|
86 |
-
##-------------------start-of-_translate_message()---------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
87 |
-
|
88 |
-
## backoff wrapper for retrying on errors, As of OpenAI > 1.0.0, it comes with a built in backoff system, but I've grown accustomed to this one so I'm keeping it.
|
89 |
-
@staticmethod
|
90 |
-
async def _translate_message(translation_instructions:Message, translation_prompt:Message) -> str:
|
91 |
-
|
92 |
-
"""
|
93 |
-
|
94 |
-
Translates a system and user message.
|
95 |
-
|
96 |
-
Parameters:
|
97 |
-
translation_instructions (object - SystemTranslationMessage | ModelTranslationMessage) : The system message also known as the instructions.
|
98 |
-
translation_prompt (object - ModelTranslationMessage) : The user message also known as the prompt.
|
99 |
-
|
100 |
-
Returns:
|
101 |
-
output (string) a string that gpt gives to us also known as the translation.
|
102 |
-
|
103 |
-
"""
|
104 |
-
|
105 |
-
if(OpenAIService.client.api_key == "DummyKey"):
|
106 |
-
raise InvalidAPIKeyException("OpenAI")
|
107 |
-
|
108 |
-
## logit bias is currently excluded due to a lack of need, and the fact that i am lazy
|
109 |
-
|
110 |
-
response = await OpenAIService.client.chat.completions.create(
|
111 |
-
model=OpenAIService.model,
|
112 |
-
messages=[
|
113 |
-
translation_instructions.to_dict(),
|
114 |
-
translation_prompt.to_dict()
|
115 |
-
], # type: ignore
|
116 |
-
|
117 |
-
temperature = OpenAIService.temperature,
|
118 |
-
top_p = OpenAIService.top_p,
|
119 |
-
n = OpenAIService.n,
|
120 |
-
stream = OpenAIService.stream,
|
121 |
-
stop = OpenAIService.stop,
|
122 |
-
presence_penalty = OpenAIService.presence_penalty,
|
123 |
-
frequency_penalty = OpenAIService.frequency_penalty,
|
124 |
-
max_tokens = OpenAIService.max_tokens
|
125 |
-
|
126 |
-
)
|
127 |
-
|
128 |
-
## if anyone knows how to type hint this please let me know
|
129 |
-
output = response.choices[0].message.content
|
130 |
-
|
131 |
-
return output
|
132 |
-
|
133 |
-
##-------------------start-of-test_api_key_validity()---------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
134 |
-
|
135 |
-
@staticmethod
|
136 |
-
async def test_api_key_validity() -> typing.Tuple[bool, typing.Union[Exception, None]]:
|
137 |
-
|
138 |
-
"""
|
139 |
-
|
140 |
-
Tests the validity of the API key.
|
141 |
-
|
142 |
-
Returns:
|
143 |
-
validity (bool) : True if the API key is valid, False if it is not.
|
144 |
-
e (Exception) : The exception that was raised, if any.
|
145 |
-
|
146 |
-
"""
|
147 |
-
|
148 |
-
validity = False
|
149 |
-
|
150 |
-
try:
|
151 |
-
|
152 |
-
await OpenAIService.client.chat.completions.create(
|
153 |
-
model="gpt-3.5-turbo",
|
154 |
-
messages=[{"role":"user","content":"This is a test."}],
|
155 |
-
max_tokens=1
|
156 |
-
)
|
157 |
-
|
158 |
-
validity = True
|
159 |
-
|
160 |
-
return validity, None
|
161 |
-
|
162 |
-
except Exception as e:
|
163 |
-
|
164 |
-
return validity, e
|
165 |
-
|
166 |
-
##-------------------start-of-get_decorator()---------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
167 |
-
|
168 |
-
@staticmethod
|
169 |
-
def get_decorator() -> typing.Union[typing.Callable, None]:
|
170 |
-
|
171 |
-
"""
|
172 |
-
|
173 |
-
Returns the decorator to use for the OpenAI service.
|
174 |
-
|
175 |
-
Returns:
|
176 |
-
decorator (callable) : The decorator to use.
|
177 |
-
|
178 |
-
"""
|
179 |
-
|
180 |
-
return OpenAIService.decorator_to_use
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
util/token_counter.py
CHANGED
@@ -11,9 +11,11 @@ parent_dir = current_dir.parent
|
|
11 |
## Add the parent directory to sys.path so 'modules' can be found
|
12 |
sys.path.append(str(parent_dir))
|
13 |
|
|
|
|
|
|
|
14 |
## custom modules
|
15 |
from modules.common.toolkit import Toolkit
|
16 |
-
from models.kijiku import Kijiku
|
17 |
|
18 |
class TokenCounter:
|
19 |
|
@@ -37,28 +39,6 @@ class TokenCounter:
|
|
37 |
|
38 |
self.MODEL:str = ""
|
39 |
|
40 |
-
##-------------------start-of-count_characters()---------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
41 |
-
|
42 |
-
def count_characters(self) -> int:
|
43 |
-
|
44 |
-
"""
|
45 |
-
|
46 |
-
Counts the number of characters in a string.
|
47 |
-
|
48 |
-
Parameters:
|
49 |
-
self (object - TokenCounter) : The TokenCounter object.
|
50 |
-
|
51 |
-
Returns:
|
52 |
-
num_characters (int) The number of characters in the text.
|
53 |
-
|
54 |
-
"""
|
55 |
-
|
56 |
-
Toolkit.clear_console()
|
57 |
-
|
58 |
-
num_characters = len(self.text)
|
59 |
-
|
60 |
-
return num_characters
|
61 |
-
|
62 |
##-------------------start-of-estimate_cost()---------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
63 |
|
64 |
def estimate_cost(self, text_file:str) -> None:
|
@@ -78,17 +58,19 @@ class TokenCounter:
|
|
78 |
self.text = file.read()
|
79 |
|
80 |
self.MODEL = input("Please enter model : ")
|
|
|
81 |
|
82 |
-
|
83 |
-
Kijiku.text_to_translate = [line for line in self.text.splitlines()]
|
84 |
|
85 |
-
num_tokens, min_cost, self.MODEL =
|
86 |
-
num_characters = self.count_characters()
|
87 |
|
88 |
-
print("
|
89 |
-
|
90 |
-
|
91 |
-
|
|
|
|
|
|
|
92 |
|
93 |
Toolkit.pause_console()
|
94 |
|
|
|
11 |
## Add the parent directory to sys.path so 'modules' can be found
|
12 |
sys.path.append(str(parent_dir))
|
13 |
|
14 |
+
## third-party libraries
|
15 |
+
from easytl import EasyTL
|
16 |
+
|
17 |
## custom modules
|
18 |
from modules.common.toolkit import Toolkit
|
|
|
19 |
|
20 |
class TokenCounter:
|
21 |
|
|
|
39 |
|
40 |
self.MODEL:str = ""
|
41 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
42 |
##-------------------start-of-estimate_cost()---------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
43 |
|
44 |
def estimate_cost(self, text_file:str) -> None:
|
|
|
58 |
self.text = file.read()
|
59 |
|
60 |
self.MODEL = input("Please enter model : ")
|
61 |
+
self.service = "openai" if "gpt" in self.MODEL else "gemini"
|
62 |
|
63 |
+
text_to_translate = [line for line in self.text.splitlines()]
|
|
|
64 |
|
65 |
+
num_tokens, min_cost, self.MODEL = EasyTL.calculate_cost(text=text_to_translate, service=self.service, model=self.MODEL)
|
|
|
66 |
|
67 |
+
print("\nNote that the cost estimate is not always accurate, and may be higher than the actual cost. However cost calculation now includes output tokens.\n")
|
68 |
+
|
69 |
+
if(self.service == "gemini"):
|
70 |
+
print(f"As of Kudasai {Toolkit.CURRENT_VERSION}, Gemini Pro 1.0 is free to use under 60 requests per minute, Gemini Pro 1.5 is free to use under 2 requests per minute.\nIt is up to you to set these in the settings json.\nIt is currently unknown whether the ultra model parameter is connecting to the actual ultra model and not a pro one. As it works, but does not appear on any documentation.\n")
|
71 |
+
|
72 |
+
print("Estimated number of tokens : " + str(num_tokens))
|
73 |
+
print("Estimated minimum cost : " + str(min_cost) + " USD")
|
74 |
|
75 |
Toolkit.pause_console()
|
76 |
|
webgui.py
CHANGED
@@ -7,7 +7,9 @@ import gradio as gr
|
|
7 |
|
8 |
from kairyou import Indexer
|
9 |
from kairyou import Kairyou
|
10 |
-
from kairyou
|
|
|
|
|
11 |
|
12 |
## custom modules
|
13 |
from modules.common.toolkit import Toolkit
|
@@ -21,10 +23,6 @@ from handlers.json_handler import JsonHandler
|
|
21 |
|
22 |
from models.kaiseki import Kaiseki
|
23 |
from models.kijiku import Kijiku
|
24 |
-
from translation_services.deepl_service import DeepLService
|
25 |
-
|
26 |
-
from translation_services.openai_service import OpenAIService
|
27 |
-
from translation_services.gemini_service import GeminiService
|
28 |
|
29 |
from kudasai import Kudasai
|
30 |
|
@@ -165,15 +163,14 @@ class KudasaiGUI:
|
|
165 |
## next api key
|
166 |
try:
|
167 |
if(Kijiku.LLM_TYPE == "openai"):
|
168 |
-
|
169 |
-
is_valid, e =
|
170 |
|
171 |
|
172 |
else:
|
173 |
|
174 |
-
|
175 |
-
|
176 |
-
is_valid, e = await GeminiService.test_api_key_validity()
|
177 |
|
178 |
if(is_valid == False and e is not None):
|
179 |
raise e
|
@@ -498,7 +495,7 @@ class KudasaiGUI:
|
|
498 |
|
499 |
self.openai_model_input_field = gr.Dropdown(label="OpenAI Model",
|
500 |
value=str(GuiJsonUtil.fetch_kijiku_setting_key_values("openai settings","openai_model")),
|
501 |
-
choices=[model for model in
|
502 |
info="ID of the model to use. Kijiku only works with 'chat' models.",
|
503 |
show_label=True,
|
504 |
interactive=True,
|
@@ -600,7 +597,7 @@ class KudasaiGUI:
|
|
600 |
|
601 |
self.gemini_model_input_field = gr.Dropdown(label="Gemini Model",
|
602 |
value=str(GuiJsonUtil.fetch_kijiku_setting_key_values("gemini settings","gemini_model")),
|
603 |
-
choices=[model for model in
|
604 |
info="The model to use. Currently only supports gemini-pro and gemini-pro-vision, the 1.0 model and it's aliases.",
|
605 |
show_label=True,
|
606 |
interactive=True,
|
@@ -905,9 +902,9 @@ class KudasaiGUI:
|
|
905 |
text_to_translate = input_text
|
906 |
|
907 |
try:
|
908 |
-
|
909 |
|
910 |
-
is_valid, e =
|
911 |
|
912 |
if(is_valid == False and e is not None):
|
913 |
raise e
|
@@ -1064,8 +1061,6 @@ class KudasaiGUI:
|
|
1064 |
else:
|
1065 |
Kijiku.LLM_TYPE = "gemini"
|
1066 |
|
1067 |
-
## normally done in Kijiku.commence_translation, but since we're not translating, we need to do it here
|
1068 |
-
GeminiService.redefine_client()
|
1069 |
|
1070 |
await set_kijiku_api_key(api_key)
|
1071 |
|
@@ -1077,15 +1072,15 @@ class KudasaiGUI:
|
|
1077 |
else:
|
1078 |
text_to_translate = input_text
|
1079 |
|
1080 |
-
|
1081 |
-
Kijiku.text_to_translate = [line for line in str(text_to_translate).splitlines()]
|
1082 |
|
1083 |
-
num_tokens, estimated_cost, model = Kijiku.
|
1084 |
|
1085 |
if(Kijiku.LLM_TYPE == "gemini"):
|
1086 |
-
cost_estimation = f"As of Kudasai {Toolkit.CURRENT_VERSION}, Gemini Pro is
|
1087 |
|
1088 |
cost_estimation += "Estimated number of tokens : " + str(num_tokens) + "\n" + "Estimated minimum cost : " + str(estimated_cost) + " USD"
|
|
|
1089 |
|
1090 |
gr.Info(cost_estimation)
|
1091 |
|
@@ -1401,7 +1396,7 @@ class KudasaiGUI:
|
|
1401 |
gemini_max_output_tokens_value
|
1402 |
]
|
1403 |
|
1404 |
-
gr.Info("Kijiku Settings Reset to Default")
|
1405 |
|
1406 |
return return_batch
|
1407 |
|
|
|
7 |
|
8 |
from kairyou import Indexer
|
9 |
from kairyou import Kairyou
|
10 |
+
from kairyou import InvalidReplacementJsonKeys
|
11 |
+
|
12 |
+
from easytl import EasyTL, ALLOWED_GEMINI_MODELS, ALLOWED_OPENAI_MODELS
|
13 |
|
14 |
## custom modules
|
15 |
from modules.common.toolkit import Toolkit
|
|
|
23 |
|
24 |
from models.kaiseki import Kaiseki
|
25 |
from models.kijiku import Kijiku
|
|
|
|
|
|
|
|
|
26 |
|
27 |
from kudasai import Kudasai
|
28 |
|
|
|
163 |
## next api key
|
164 |
try:
|
165 |
if(Kijiku.LLM_TYPE == "openai"):
|
166 |
+
EasyTL.set_api_key(Kijiku.LLM_TYPE, str(api_key))
|
167 |
+
is_valid, e = EasyTL.test_api_key_validity(Kijiku.LLM_TYPE)
|
168 |
|
169 |
|
170 |
else:
|
171 |
|
172 |
+
EasyTL.set_api_key(Kijiku.LLM_TYPE, str(api_key))
|
173 |
+
is_valid, e = EasyTL.test_api_key_validity(Kijiku.LLM_TYPE)
|
|
|
174 |
|
175 |
if(is_valid == False and e is not None):
|
176 |
raise e
|
|
|
495 |
|
496 |
self.openai_model_input_field = gr.Dropdown(label="OpenAI Model",
|
497 |
value=str(GuiJsonUtil.fetch_kijiku_setting_key_values("openai settings","openai_model")),
|
498 |
+
choices=[model for model in ALLOWED_OPENAI_MODELS],
|
499 |
info="ID of the model to use. Kijiku only works with 'chat' models.",
|
500 |
show_label=True,
|
501 |
interactive=True,
|
|
|
597 |
|
598 |
self.gemini_model_input_field = gr.Dropdown(label="Gemini Model",
|
599 |
value=str(GuiJsonUtil.fetch_kijiku_setting_key_values("gemini settings","gemini_model")),
|
600 |
+
choices=[model for model in ALLOWED_GEMINI_MODELS],
|
601 |
info="The model to use. Currently only supports gemini-pro and gemini-pro-vision, the 1.0 model and it's aliases.",
|
602 |
show_label=True,
|
603 |
interactive=True,
|
|
|
902 |
text_to_translate = input_text
|
903 |
|
904 |
try:
|
905 |
+
EasyTL.set_api_key("deepl", str(api_key_input))
|
906 |
|
907 |
+
is_valid, e = EasyTL.test_api_key_validity("deepl")
|
908 |
|
909 |
if(is_valid == False and e is not None):
|
910 |
raise e
|
|
|
1061 |
else:
|
1062 |
Kijiku.LLM_TYPE = "gemini"
|
1063 |
|
|
|
|
|
1064 |
|
1065 |
await set_kijiku_api_key(api_key)
|
1066 |
|
|
|
1072 |
else:
|
1073 |
text_to_translate = input_text
|
1074 |
|
1075 |
+
translation_instructions = GuiJsonUtil.fetch_kijiku_setting_key_values("openai settings","openai_system_message") if Kijiku.LLM_TYPE == "openai" else GuiJsonUtil.fetch_kijiku_setting_key_values("gemini settings","gemini_prompt")
|
|
|
1076 |
|
1077 |
+
num_tokens, estimated_cost, model = EasyTL.calculate_cost(text=text_to_translate, service=Kijiku.LLM_TYPE, model=model, translation_instructions=translation_instructions)
|
1078 |
|
1079 |
if(Kijiku.LLM_TYPE == "gemini"):
|
1080 |
+
cost_estimation = f"As of Kudasai {Toolkit.CURRENT_VERSION}, Gemini Pro 1.0 is free to use under 60 requests per minute, Gemini Pro 1.5 is free to use under 2 requests per minute.\nIt is up to you to set these in the settings json.\nIt is currently unknown whether the ultra model parameter is connecting to the actual ultra model and not a pro one. As it works, but does not appear on any documentation.\n"
|
1081 |
|
1082 |
cost_estimation += "Estimated number of tokens : " + str(num_tokens) + "\n" + "Estimated minimum cost : " + str(estimated_cost) + " USD"
|
1083 |
+
cost_estimation += "\nThis is a rough estimate, please remember to check actual cost on the appropriate platform when needed"
|
1084 |
|
1085 |
gr.Info(cost_estimation)
|
1086 |
|
|
|
1396 |
gemini_max_output_tokens_value
|
1397 |
]
|
1398 |
|
1399 |
+
gr.Info("Kijiku Settings Reset to Default. Make sure to press the Apply button to apply the changes.")
|
1400 |
|
1401 |
return return_batch
|
1402 |
|