8000 Merge pull request #156 from yjg30737/Dev · DataSolveProblems/pyqt-openai@af2146a · GitHub
[go: up one dir, main page]

Skip to content

Commit af2146a

Browse files
authored
Merge pull request yjg30737#156 from yjg30737/Dev
v1.4.0
2 parents e8e4348 + 2eba47b commit af2146a

28 files changed

+909
-744
lines changed

pyproject.toml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
44

55
[project]
66
name = "pyqt-openai"
7-
version = "1.3.0"
7+
version = "1.4.0"
88
description = "Python multipurpose chatbot that user can use GPT, other AI models altogether (Release Name: VividNode)"
99
authors = [{ name = "Jung Gyu Yoon", email = "yjg30737@gmail.com" }]
1010
license = { text = "MIT" }
@@ -25,7 +25,7 @@ dependencies = [
2525
"g4f",
2626
"curl_cffi"
2727
]
28-
keywords = ['openai', 'pyqt', 'pyqt5', 'pyqt6', 'pyside6', 'desktop', 'app', 'chatbot', 'gpt', 'replicate', 'gemini', 'claude', 'llama', 'llm']
28+
keywords = ['openai', 'pyqt', 'pyqt5', 'pyqt6', 'pyside6', 'desktop', 'app', 'chatbot', 'gpt', 'replicate', 'gemini', 'claude', 'llama', 'llm', 'gpt4free']
2929

3030
requires-python = ">= 3.11"
3131
# 3.11

pyqt_openai/__init__.py

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -186,6 +186,8 @@ def move_updater():
186186
ICON_SEND = os.path.join(ICON_PATH, 'send.svg')
187187
ICON_RECORD = os.path.join(ICON_PATH, 'record.svg')
188188
ICON_SPEAKER = os.path.join(ICON_PATH, 'speaker.svg')
189+
ICON_PAYPAL = os.path.join(ICON_PATH, 'paypal.png')
190+
ICON_KOFI = os.path.join(ICON_PATH, 'kofi.png')
189191

190192
## CUSTOMIZE
191193
DEFAULT_ICON_SIZE = (24, 24)
@@ -247,7 +249,14 @@ def move_updater():
247249
MAIN_INDEX = 'main.py'
248250
IMAGE_DEFAULT_SAVE_DIRECTORY = 'image_result'
249251
INI_FILE_NAME = os.path.join(get_config_directory(), 'config.yaml')
250-
LANGUAGE_FILE = os.path.join(get_config_directory(), 'translations.json')
252+
LANGUAGE_FILE_BASE_NAME = 'translations.json'
253+
LANGUAGE_FILE = os.path.join(get_config_directory(), LANGUAGE_FILE_BASE_NAME)
254+
LANGUAGE_FILE_SRC = os.path.join(os.path.join(EXEC_PATH, 'lang'), LANGUAGE_FILE_BASE_NAME)
255+
256+
# Make sure the language file exists
257+
if not os.path.exists(LANGUAGE_FILE):
258+
shutil.copy(LANGUAGE_FILE_SRC, LANGUAGE_FILE)
259+
251260

252261
DB_FILE_NAME = 'conv'
253262
FILE_NAME_LENGTH = 32
@@ -355,6 +364,8 @@ def move_updater():
355364
# This doesn't need endpoint
356365
DALLE_ARR = ['dall-e-2', 'dall-e-3']
357366

367+
DEFAULT_DATETIME_FORMAT = '%Y-%m-%d %H:%M:%S'
368+
358369
OPENAI_CHAT_ENDPOINT = '/v1/chat/completions'
359370

360371
# Other models' configuration data
@@ -392,6 +403,8 @@ def move_updater():
392403

393404
G4F_PROVIDER_DEFAULT = 'Auto'
394405

406+
G4F_USE_CHAT_HISTORY = True
407+
395408
# Dictionary that stores the platform and model pairs
396409
PROVIDER_MODEL_DICT = {
397410
'OpenAI': ['gpt-4o', 'gpt-4o-mini']+O1_MODELS,
@@ -529,7 +542,12 @@ def move_updater():
529542
'OPENAI_API_KEY': '',
530543
'GEMINI_API_KEY': '',
531544
'CLAUDE_API_KEY': '',
532-
'LLAMA_API_KEY': ''
545+
'LLAMA_API_KEY': '',
546+
547+
# G4F
548+
'g4f_model': DEFAULT_LLM,
549+
'provider': G4F_PROVIDER_DEFAULT,
550+
'g4f_use_chat_history': G4F_USE_CHAT_HISTORY,
533551
},
534552
'DALLE': {
535553
'quality': 'standard',

pyqt_openai/chat_widget/center/aiChatUnit.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,8 @@
66
from pyqt_openai.chat_widget.center.chatUnit import ChatUnit
77
from pyqt_openai.chat_widget.center.responseInfoDialog import ResponseInfoDialog
88
from pyqt_openai.models import ChatMessageContainer
9-
from pyqt_openai.globals import DB, stream_to_speakers
9+
from pyqt_openai.globals import DB
10+
from pyqt_openai.util.script import stream_to_speakers
1011
from pyqt_openai.widgets.button import Button
1112

1213

pyqt_openai/chat_widget/center/chatWidget.py

Lines changed: 13 additions & 7 deletions
111C
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,14 @@
44
from PySide6.QtCore import Signal
55
from PySide6.QtWidgets import QStackedWidget, QWidget, QSizePolicy, QHBoxLayout, QVBoxLayout, QMessageBox
66

7-
from pyqt_openai.config_loader import CONFIG_MANAGER
8-
from pyqt_openai.globals import LLAMAINDEX_WRAPPER, DB, get_openai_chat_model, get_argument, ChatThread
97
from pyqt_openai.chat_widget.center.chatBrowser import ChatBrowser
108
from pyqt_openai.chat_widget.center.chatHome import ChatHome
119
from pyqt_openai.chat_widget.center.menuWidget import MenuWidget
1210
from pyqt_openai.chat_widget.center.prompt import Prompt
13-
from pyqt_openai.chat_widget.chatThread import LlamaOpenAIThread
11+
from pyqt_openai.chat_widget.llamaOpenAIThread import LlamaOpenAIThread
12+
from pyqt_openai.config_loader import CONFIG_MANAGER
13+
from pyqt_openai.globals import LLAMAINDEX_WRAPPER, DB
14+
from pyqt_openai.util.script import get_argument, ChatThread
1415
from pyqt_openai.lang.translations import LangClass
1516
from pyqt_openai.models import ChatMessageContainer
1617
from pyqt_openai.widgets.notifier import NotifierWidget
@@ -21,7 +22,7 @@ class ChatWidget(QWidget):
2122
onMenuCloseClicked = Signal()
2223

2324
def __init__(self, parent=None):
24-
super(ChatWidget, self).__init__(parent)
25+
super().__init__(parent)
2526
self.__initVal()
2627
self.__initUi()
2728

@@ -115,7 +116,7 @@ def __chat(self):
115116
try:
116117
# Get necessary parameters
117118
stream = CONFIG_MANAGER.get_general_property('stream')
118-
model = CONFIG_MANAGER.get_general_property('model')
119+
model = CONFIG_MANAGER.get_general_property('g4f_model') if self.__is_g4f else CONFIG_MANAGER.get_general_property('model')
119120
system = CONFIG_MANAGER.get_general_property('system')
120121
temperature = CONFIG_MANAGER.get_general_property('temperature')
121122
max_tokens = CONFIG_MANAGER.get_general_property('max_tokens')
@@ -125,11 +126,16 @@ def __chat(self):
125126
presence_penalty = CONFIG_MANAGER.get_general_property('presence_penalty')
126127
use_llama_index = CONFIG_MANAGER.get_general_property('use_llama_index')
127128
use_max_tokens = CONFIG_MANAGER.get_general_property('use_max_tokens')
129+
provider = CONFIG_MANAGER.get_general_property('provider')
130+
g4f_use_chat_history = CONFIG_MANAGER.get_general_property('g4f_use_chat_history')
128131

129132
# Get image files
130133
images = self.__prompt.getImageBuffers()
131134

132-
messages = self.__browser.getMessages(CONFIG_MANAGER.get_general_property('maximum_messages_in_parameter'))
135+
maximum_messages_in_parameter = CONFIG_MANAGER.get_general_property('maximum_messages_in_parameter')
136+
messages = self.__browser.getMessages(maximum_messages_in_parameter)
137+
if self.__is_g4f and not g4f_use_chat_history:
138+
messages = []
133139

134140
cur_text = self.__prompt.getContent()
135141

@@ -197,7 +203,7 @@ def __chat(self):
197203
# Run a different thread based on whether the llama-index is enabled or not.
198204
self.__t = LlamaOpenAIThread(param, container, LLAMAINDEX_WRAPPER, query_text)
199205
else:
200-
self.__t = ChatThread(param, info=container, is_g4f=self.__is_g4f)
206+
self.__t = ChatThread(param, info=container, is_g4f=self.__is_g4f, provider=provider)
201207

202208
self.__t.started.connect(self.__beforeGenerated)
203209
self.__t.replyGenerated.connect(self.__browser.showLabel)

pyqt_openai/chat_widget/center/messageTextBrowser.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ def adjustBrowserHeight(self):
5151
self.setMinimumHeight(int(max_height))
5252
self.verticalScrollBar().setSliderPosition(self.verticalScrollBar().maximum())
5353

54-
# TODO WILL_BE_IMPLEMENTED AFTER v1.3.0
54+
# TODO WILL_BE_IMPLEMENTED AFTER v1.4.0
5555
def setMarkdown(self, markdown: str) -> None:
5656
super().setMarkdown(markdown)
5757
# Convert markdown to HTML using QTextDocument

pyqt_openai/chat_widget/center/prompt.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,12 +11,12 @@
1111
IMAGE_FILE_EXT_LIST, \
1212
TEXT_FILE_EXT_LIST, QFILEDIALOG_DEFAULT_DIRECTORY, DEFAULT_SHORTCUT_SEND, DEFAULT_SHORTCUT_RECORD, ICON_RECORD
1313
from pyqt_openai.config_loader import CONFIG_MANAGER
14-
from pyqt_openai.globals import DB, STTThread, RecorderThread
14+
from pyqt_openai.globals import DB
1515
from pyqt_openai.chat_widget.center.commandSuggestionWidget import CommandSuggestionWidget
1616
from pyqt_openai.chat_widget.center.textEditPromptGroup import TextEditPromptGroup
1717
from pyqt_openai.chat_widget.center.uploadedImageFileWidget import UploadedImageFileWidget
1818
from pyqt_openai.lang.translations import LangClass
19-
from pyqt_openai.util.script import get_content_of_text_file_for_send
19+
from pyqt_openai.util.script import get_content_of_text_file_for_send, RecorderThread, STTThread
2020
from pyqt_openai.widgets.button import Button
2121
from pyqt_openai.widgets.toolButton import ToolButton
2222

pyqt_openai/chat_widget/chatMainWidget.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ def __initUi(self):
5252

5353
self.__chatRightSideBarWidget = ChatRightSideBarWidget()
5454
self.__chatRightSideBarWidget.onToggleJSON.connect(self.__chatWidget.toggleJSON)
55+
5556
self.__chatRightSideBarWidget.onTabChanged.connect(self.__chatWidget.setG4F)
5657

5758
self.__chatWidget.setG4F(self.__chatRightSideBarWidget.currentTabIdx())

pyqt_openai/chat_widget/chatThread.py renamed to pyqt_openai/chat_widget/llamaOpenAIThread.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,12 @@
11
from llama_index.core.base.response.schema import StreamingResponse
22
from PySide6.QtCore import QThread, Signal
33

4+
import pyqt_openai.util.script
45
from pyqt_openai.models import ChatMessageContainer
56

67

8+
# TODO
9+
# Should combine with ChatThread
710
class LlamaOpenAIThread(QThread):
811
replyGenerated = Signal(str, bool, ChatMessageContainer)
912
streamFinished = Signal(ChatMessageContainer)
@@ -24,7 +27,7 @@ def stop(self):
2427

2528
def run(self):
2629
try:
27-
resp = self.__wrapper.get_response(self.__query_text)
30+
resp = pyqt_openai.util.script.get_response(self.__query_text)
2831
f = isinstance(resp, StreamingResponse)
2932
if f:
3033
for response_text in resp.response_gen:

pyqt_openai/chat_widget/right_sidebar/apiWidget.py

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,9 @@
33
QDialogButtonBox, QWidget, QPushButton
44

55
from pyqt_openai import HOW_TO_GET_OPENAI_API_KEY_URL, HOW_TO_GET_CLAUDE_API_KEY_URL, HOW_TO_GET_GEMINI_API_KEY_URL, \
6-
HOW_TO_GET_LLAMA_API_KEY_URL, DEFAULT_API_CONFIGS
6+
HOW_TO_GET_LLAMA_API_KEY_URL, DEFAULT_API_CONFIGS, HOW_TO_REPLICATE
77
from pyqt_openai.config_loader import CONFIG_MANAGER
8-
from pyqt_openai.globals import set_api_key
8+
from pyqt_openai.util.script import set_api_key
99
from pyqt_openai.widgets.linkLabel import LinkLabel
1010

1111

@@ -33,13 +33,21 @@ def __initVal(self):
3333
}
3434
self.__api_keys.append(_conf)
3535

36+
# Add REPLICATE API
37+
self.__api_keys.append({
38+
'display_name': 'Replicate',
39+
'env_var_name': 'REPLICATE_API_TOKEN',
40+
'api_key': CONFIG_MANAGER.get_replicate_property('REPLICATE_API_TOKEN')
41+
})
42+
3643
# Set "get api key" here
3744
for i, obj in enumerate(self.__api_keys):
3845
obj['get_api_key'] = {
3946
'OpenAI': HOW_TO_GET_OPENAI_API_KEY_URL,
4047
'Claude': HOW_TO_GET_CLAUDE_API_KEY_URL,
4148
'Gemini': HOW_TO_GET_GEMINI_API_KEY_URL,
42-
'Llama': HOW_TO_GET_LLAMA_API_KEY_URL
49+
'Llama': HOW_TO_GET_LLAMA_API_KEY_URL,
50+
'Replicate': HOW_TO_REPLICATE
4351
}[obj['display_name']]
4452

4553
def __initUi(self):
@@ -87,5 +95,8 @@ def setApiKeys(self):
8795
api_keys = {self.__api_keys[i]['env_var_name']: self.__tableWidget.cellWidget(i, 1).text() for i in range(self.__tableWidget.rowCount())}
8896
# Save the api keys to the conf file
8997
for k, v in api_keys.items():
90-
CONFIG_MANAGER.set_general_property(k, v)
98+
if k == 'REPLICATE_API_TOKEN':
99+
CONFIG_MANAGER.set_replicate_property(k, v)
100+
else:
101+
CONFIG_MANAGER.set_general_property(k, v)
91102
set_api_key(k, v)

pyqt_openai/chat_widget/right_sidebar/usingAPIPage.py

Lines changed: 28 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,10 @@
55
from pyqt_openai import DEFAULT_SHORTCUT_JSON_MODE, OPENAI_TEMPERATURE_RANGE, OPENAI_TEMPERATURE_STEP, \
66
MAX_TOKENS_RANGE, TOP_P_RANGE, TOP_P_STEP, FREQUENCY_PENALTY_RANGE, PRESENCE_PENALTY_STEP, PRESENCE_PENALTY_RANGE, \
77
FREQUENCY_PENALTY_STEP, LLAMAINDEX_URL
8-
from pyqt_openai.chat_widget.right_sidebar.apiWidget import ApiWidget
98
from pyqt_openai.config_loader import CONFIG_MANAGER
109
from pyqt_openai.lang.translations import LangClass
11-
from pyqt_openai.globals import init_llama, get_openai_chat_model
12-
from pyqt_openai.util.script import getSeparator, get_chat_model
10+
from pyqt_openai.settings_dialog.settingsDialog import SettingsDialog
11+
from pyqt_openai.util.script import getSeparator, get_chat_model, get_openai_chat_model, init_llama
1312
from pyqt_openai.widgets.linkLabel import LinkLabel
1413

1514

@@ -76,7 +75,30 @@ def __initUi(self):
7675
lay.addWidget(modelCmbBox)
7776
lay.setContentsMargins(0, 0, 0, 0)
7877

79-
apiWidget = ApiWidget()
78+
# TODO LANGUAGE
79+
setApiBtn = QPushButton('Set API Key')
80+
setApiBtn.clicked.connect(lambda _: SettingsDialog(default_index=1, parent=self).exec_())
81+
setApiBtn.setStyleSheet('''
82+
QPushButton {
83+
background-color: #007BFF;
84+
color: white;
85+
border-radius: 8px;
86+
padding: 10px 20px;
87+
font-size: 16px;
88+
font-family: "Arial";
89+
font-weight: bold;
90+
border: 2px solid #007BFF;
91+
}
92+
QPushButton:hover {
93+
background-color: #0056b3;
94+
border-color: #0056b3;
95+
}
96+
QPushButton:pressed {
97+
background-color: #003f7f;
98+
border-color: #003f7f;
99+
}
100+
'''
101+
)
80102

81103
selectModelWidget = QWidget()
82104
selectModelWidget.setLayout(lay)
@@ -86,10 +108,7 @@ def __initUi(self):
86108
self.__warningLbl.setVisible(False)
87109

88110
# TODO WILL_BE_REMOVED_AFTER v1.5.0
89-
self.__warningLbl.setText('Currently LlamaIndex, JSON mode, and Image input are only available for the OpenAI Chat model.\n'
90-
# TODO WILL_BE_REMOVED_AFTER v1.3.0
91-
'Also you have to get OpenAI API key to use these features.\n'
92-
'I will update this soon.')
111+
self.__warningLbl.setText('Currently LlamaIndex, JSON mode, and Image input are only available for the OpenAI Chat model.')
93112
self.__warningLbl.setWordWrap(True)
94113

95114
advancedSettingsScrollArea = QScrollArea()
@@ -196,7 +215,7 @@ def __initUi(self):
196215
lay.addWidget(self.__systemTextEdit)
197216
lay.addWidget(saveSystemBtn)
198217
lay.addWidget(getSeparator('horizontal'))
199-
lay.addWidget(apiWidget)
218+
lay.addWidget(setApiBtn)
200219
lay.addWidget(selectModelWidget)
201220
lay.addWidget(self.__warningLbl)
202221
lay.addWidget(streamChkBox)

pyqt_openai/chat_widget/right_sidebar/usingG4FPage.py

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,8 @@ def __init__(self, parent=None):
1919

2020
def __initVal(self):
2121
self.__stream = CONFIG_MANAGER.get_general_property('stream')
22-
self.__model = CONFIG_MANAGER.get_general_property('model')
22+
self.__model = CONFIG_MANAGER.get_general_property('g4f_model')
23+
self.__provider = CONFIG_MANAGER.get_general_property('provider')
2324

2425
def __initUi(self):
2526
manualBrowser = QTextBrowser()
@@ -47,29 +48,41 @@ def __initUi(self):
4748

4849
providerCmbBox = QComboBox()
4950
providerCmbBox.addItems(get_g4f_providers(including_auto=True))
51+
providerCmbBox.setCurrentText(self.__provider)
5052
providerCmbBox.currentTextChanged.connect(self.__providerChanged)
5153

54+
# TODO LANGUAGE
55+
# TODO NEEDS ADDITIONAL DESCRIPTION
56+
g4f_use_chat_historyChkBox = QCheckBox('Use chat history')
57+
g4f_use_chat_historyChkBox.setChecked(CONFIG_MANAGER.get_general_property('g4f_use_chat_history'))
58+
g4f_use_chat_historyChkBox.toggled.connect(self.__saveChatHistory)
59+
5260
lay = QFormLayout()
5361
lay.addRow(manualBrowser)
5462
lay.addRow(getSeparator('horizontal'))
5563
lay.addRow('Model', self.__modelCmbBox)
5664
lay.addRow('Provider', providerCmbBox)
5765
lay.addRow(streamChkBox)
66+
lay.addRow(g4f_use_chat_historyChkBox)
5867
lay.setAlignment(Qt.AlignmentFlag.AlignTop)
5968

6069
self.setLayout(lay)
6170

6271
def __modelChanged(self, v):
6372
self.__model = v
64-
CONFIG_MANAGER.set_general_property('model', v)
73+
CONFIG_MANAGER.set_general_property('g4f_model', v)
6574

6675
def __streamChecked(self, f):
6776
self.__stream = f
6877
CONFIG_MANAGER.set_general_property('stream', f)
6978

7079
def __providerChanged(self, v):
7180
self.__modelCmbBox.clear()
81+
CONFIG_MANAGER.set_general_property('provider', v)
7282
if v == G4F_PROVIDER_DEFAULT:
7383
self.__modelCmbBox.addItems(get_g4f_models())
7484
else:
75-
self.__modelCmbBox.addItems(get_g4f_models_by_provider(v))
85+
self.__modelCmbBox.addItems(get_g4f_models_by_provider(v))
86+
87+
def __saveChatHistory(self, f):
88+
CONFIG_MANAGER.set_general_property('g4f_use_chat_history', f)

0 commit comments

Comments
 (0)
0