From 4ba3725ef735b8b062b742036d92f1ffd24dd8d7 Mon Sep 17 00:00:00 2001
From: berkaygediz <121058050+berkaygediz@users.noreply.github.com>
Date: Thu, 27 Feb 2025 00:57:52 +0300
Subject: [PATCH] =?UTF-8?q?=F0=9F=9A=80=20Real-time=20LLM=20response,=20ma?=
=?UTF-8?q?ximized=20GPU/NPU=20performance,=20fixed=20memory=20leaks,=20en?=
=?UTF-8?q?hanced=20LLM=20threading,=20improved=20hybrid=20saver=20adaptiv?=
=?UTF-8?q?e=20response=20rates,=20updated=20requirements,=20bullet/number?=
=?UTF-8?q?ed=20list=20improvements,=20document=20defaults,=20toolbar=20en?=
=?UTF-8?q?hancements,=20gitignore,=20file=5Fversion=5Finfo,=20metadata,?=
=?UTF-8?q?=20version.rc?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.gitignore | 1 +
README.md | 8 +-
SolidWriting.py | 373 +++++++++++++++++++++++-------------------
file_version_info.txt | 8 +-
metadata.yml | 2 +-
requirements.txt | 10 +-
version.rc | 30 ++++
7 files changed, 247 insertions(+), 185 deletions(-)
create mode 100644 version.rc
diff --git a/.gitignore b/.gitignore
index 06a4ed6..b748abe 100644
--- a/.gitignore
+++ b/.gitignore
@@ -173,4 +173,5 @@ cython_debug/
# Built Visual Studio Code Extensions
*.vsix
+
*.gguf
\ No newline at end of file
diff --git a/README.md b/README.md
index e099feb..e321344 100644
--- a/README.md
+++ b/README.md
@@ -65,13 +65,7 @@ SolidWriting is a supercharged word processor offering a powerful alternative to
3. Creating a executable file (Unsigned):
```bash
- pyinstaller --noconfirm --onefile --windowed --icon ".\solidwriting_icon.ico" --name "SolidWriting" --clean --optimize "2" "SolidWriting.py"
- ```
-
-- Command for CUDA
-
- ```bash
- pyinstaller --noconfirm --onefile --windowed --icon ".\solidwriting_icon.ico" --name "SolidWriting" --clean --optimize "2" --add-data ".\.venv\Lib\site-packages\llama_cpp\lib\;." ".\SolidWriting.py"
+ pyinstaller --name="SolidWriting" --onedir --windowed --icon=".\solidwriting_icon.ico" --add-data "./.venv/Lib/site-packages/PySide6/*:PySide6" --add-data "./.venv/Lib/site-packages/torch/*:torch" --add-data "./.venv/Lib/site-packages/llama_cpp/*:llama_cpp" --add-binary "./.venv/Lib/site-packages/PySide6/*:PySide6" --add-binary "./.venv/Lib/site-packages/torch/*:torch" --add-binary "./.venv/Lib/site-packages/llama_cpp/*:llama_cpp" --optimize "2" --clean --noconfirm ".\SolidWriting.py"
```
## Usage
diff --git a/SolidWriting.py b/SolidWriting.py
index b573a2b..2707759 100644
--- a/SolidWriting.py
+++ b/SolidWriting.py
@@ -11,7 +11,7 @@
import psutil
import torch
from langdetect import DetectorFactory, detect
-from llama_cpp import *
+from llama_cpp import Llama
from PySide6.QtCore import *
from PySide6.QtGui import *
from PySide6.QtOpenGL import *
@@ -38,6 +38,28 @@
pass
+class LLMThread(QThread):
+ result = Signal(str)
+
+ def __init__(self, prompt, llm, parent=None):
+ super(LLMThread, self).__init__(parent)
+ self.prompt = prompt
+ self.llm = llm
+
+ def run(self):
+ response = self.getResponseLLM()
+ self.result.emit(response)
+
+ def getResponseLLM(self):
+ try:
+ response = self.llm.create_chat_completion(
+ messages=[{"role": "user", "content": self.prompt}]
+ )
+ return response["choices"][0]["message"]["content"]
+ except Exception as e:
+ return f"Error: {str(e)}"
+
+
class SW_ControlInfo(QMainWindow):
def __init__(self, parent=None):
super(SW_ControlInfo, self).__init__(parent)
@@ -100,7 +122,7 @@ def __init__(self, parent=None):
self.about_label.setText(
"
"
f"{app.applicationDisplayName()}
"
- "Real-time computing and formatting supported word processor.
"
+ "A supercharged word processor with AI integration, supporting real-time computing and advanced formatting.
"
"Made by Berkay Gediz
"
"GNU General Public License v3.0
GNU LESSER GENERAL PUBLIC LICENSE v3.0
Mozilla Public License Version 2.0
Libraries: mwilliamson/python-mammoth, Mimino666/langdetect, abetlen/llama-cpp-python,
pytorch/pytorch, PySide6, chardet, psutil
"
"OpenGL: ON"
@@ -197,10 +219,10 @@ def initUI(self):
system_language = locale.getlocale()[1]
if system_language not in languages.items():
settings.setValue("appLanguage", "1252")
- settings.sync()
if settings.value("adaptiveResponse") == None:
settings.setValue("adaptiveResponse", 1)
- settings.sync()
+
+ settings.sync()
centralWidget = QOpenGLWidget(self)
@@ -499,16 +521,7 @@ def updateStatistics(self):
statistics += f"{translations[lang]['analysis_message_5'].format(detected_language)} | "
else:
- self.DocumentArea.setFontFamily(fallbackValues["fontFamily"])
- self.DocumentArea.setFontPointSize(fallbackValues["fontSize"])
- self.DocumentArea.setFontWeight(75 if fallbackValues["bold"] else 50)
- self.DocumentArea.setFontItalic(fallbackValues["italic"])
- self.DocumentArea.setFontUnderline(fallbackValues["underline"])
- self.DocumentArea.setAlignment(fallbackValues["contentAlign"])
- self.DocumentArea.setTextColor(QColor(fallbackValues["contentColor"]))
- self.DocumentArea.setTextBackgroundColor(
- QColor(fallbackValues["contentBackgroundColor"])
- )
+ self.resetDocumentArea()
statistics += f"{translations[lang]['statistic']} | "
statistics += (
@@ -706,22 +719,11 @@ def updateToolbarLabel(self, toolbar, new_label):
return
def initArea(self):
- self.DocumentArea.setFontFamily(fallbackValues["fontFamily"])
- self.DocumentArea.setFontPointSize(fallbackValues["fontSize"])
- self.DocumentArea.setFontWeight(75 if fallbackValues["bold"] else 50)
- self.DocumentArea.setFontItalic(fallbackValues["italic"])
- self.DocumentArea.setFontUnderline(fallbackValues["underline"])
- self.DocumentArea.setAlignment(fallbackValues["contentAlign"])
- self.DocumentArea.setTextColor(QColor(fallbackValues["contentColor"]))
- self.DocumentArea.setTextBackgroundColor(
- QColor(fallbackValues["contentBackgroundColor"])
- )
- self.DocumentArea.setTabStopDistance(27)
+ self.resetDocumentArea()
self.DocumentArea.document().setDocumentMargin(self.width() * 0.25)
def loadLLM(self):
- # Consent
- if settings.value("load_llm") is None or settings.value("load_llm") is True:
+ if settings.value("load_llm") == None or settings.value("load_llm") == "true":
reply = QMessageBox.question(
None,
"Load LLM",
@@ -731,12 +733,13 @@ def loadLLM(self):
)
if reply == QMessageBox.Yes:
- settings.setValue("load_llm", True)
self._load_model()
+ settings.setValue("load_llm", True)
+
else:
- settings.setValue("load_llm", False)
- self.ai_widget.setWidget(QLabel("LLM not available."))
+ pass
else:
+ settings.setValue("load_llm", False)
self.ai_widget.setWidget(QLabel("LLM not available."))
def _load_model(self):
@@ -756,20 +759,29 @@ def _load_model(self):
model_path = os.path.join(current_directory, model_filename)
if os.path.exists(model_path):
- if torch.cuda.is_available():
- max_memory = 4 * 1024
+ if torch.accelerator.is_available() == False:
+ # max_memory = torch.cuda.get_device_properties(0).total_memory / (
+ # 1024**2
+ # ) # x MB VRAM
+ max_memory = 8192
else:
available_memory = psutil.virtual_memory().available
- max_memory = min(available_memory, 2 * 1024)
+ max_memory = min(available_memory, 4 * 1024 * 1024 * 1024) / (
+ 1024**2
+ ) # 4096 MB
self.llm = Llama(
model_path,
- n_gpu_layers=33,
- use_fp16=True,
+ n_gpu_layers=-1,
+ split_mode=0,
+ offload_kqv=True,
+ flash_attn=True,
+ n_threads=4,
max_memory=max_memory,
device_map="auto",
- n_threads=8,
+ verbose=True,
)
+
else:
self.llm = None
except TypeError as e:
@@ -854,7 +866,7 @@ def LLMinitDock(self):
QDockWidget.NoDockWidgetFeatures | QDockWidget.DockWidgetClosable
)
- def LLMmessage(self, text, is_user=True):
+ def LLMmessage(self, text, is_user=True, typing_speed=100):
DetectorFactory.seed = 0
language = ""
@@ -898,6 +910,49 @@ def LLMmessage(self, text, is_user=True):
self.messages_layout.addWidget(message_widget)
+ if not is_user:
+ self.LLMdynamicMessage(
+ message_label, text, typing_speed * self.adaptiveResponse
+ )
+
+ if is_user:
+ self.full_text = ""
+
+ def LLMdynamicMessage(self, message_label, text, typing_speed):
+ words = text.split()
+
+ if not hasattr(self, "full_text"):
+ self.full_text = ""
+
+ word_index = 0
+
+ def type_next_word():
+ nonlocal word_index
+ if word_index < len(words):
+ self.full_text += words[word_index] + " "
+ message_label.setText(self.full_text)
+ word_index += 1
+ else:
+ self.LLMmessageDatetime(message_label)
+ self.typing_timer.stop()
+
+ self.typing_timer = QTimer(self)
+ self.typing_timer.timeout.connect(type_next_word)
+ self.typing_timer.start(typing_speed)
+
+ def LLMmessageDatetime(self, message_label):
+ current_time = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
+ language = (
+ detect(message_label.text()) if len(message_label.text()) > 30 else ""
+ )
+
+ if language:
+ new_text = f"{message_label.text()}
({current_time} - {language})"
+ else:
+ new_text = f"{message_label.text()}
({current_time})"
+
+ message_label.setText(new_text)
+
def LLMpredict(self):
prompt = self.input_text.toPlainText().strip()
@@ -909,7 +964,15 @@ def LLMpredict(self):
self.predict_button.setText("...")
self.predict_button.setEnabled(False)
- QTimer.singleShot(100, lambda: self.LLMprompt(prompt))
+ self.llm_thread = LLMThread(prompt, self.llm)
+ self.llm_thread.result.connect(self.LLMhandleResponse)
+ self.llm_thread.start()
+
+ def LLMhandleResponse(self, response):
+ self.LLMmessage(response, is_user=False)
+ self.input_text.clear()
+ self.predict_button.setText("->")
+ self.predict_button.setEnabled(True)
def LLMcontextPredict(self, action_type):
selected_text = self.DocumentArea.textCursor().selectedText().strip()
@@ -928,7 +991,9 @@ def LLMcontextPredict(self, action_type):
self.LLMmessage("No text selected.", is_user=False)
return
- QTimer.singleShot(100, lambda: self.LLMprompt(prompt))
+ self.llm_thread = LLMThread(prompt, self.llm)
+ self.llm_thread.result.connect(self.LLMhandleResponse)
+ self.llm_thread.start()
def LLMprompt(self, prompt):
if prompt:
@@ -1191,27 +1256,28 @@ def initActions(self):
)
def initToolbar(self):
- self.file_toolbar = self.addToolBar(translations[lang]["file"])
- self.toolbarLabel(
- self.file_toolbar,
- translations[lang]["file"] + ": ",
- )
- self.file_toolbar.addActions(
- [
- self.newaction,
- self.openaction,
- self.saveaction,
- self.saveasaction,
- self.printaction,
- self.undoaction,
- self.redoaction,
- self.findaction,
- self.replaceaction,
- ]
- )
+ def add_toolbar(name_key, actions):
+ toolbar = self.addToolBar(translations[lang][name_key])
+ self.toolbarLabel(toolbar, translations[lang][name_key] + ": ")
+ toolbar.addActions(actions)
+ return toolbar
+
+ file_actions = [
+ self.newaction,
+ self.openaction,
+ self.saveaction,
+ self.saveasaction,
+ self.printaction,
+ self.undoaction,
+ self.redoaction,
+ self.findaction,
+ self.replaceaction,
+ ]
+ self.file_toolbar = add_toolbar("file", file_actions)
self.ui_toolbar = self.addToolBar(translations[lang]["ui"])
self.toolbarLabel(self.ui_toolbar, translations[lang]["ui"] + ": ")
+
self.theme_action = self.createAction(
translations[lang]["darklight"],
translations[lang]["darklight_message"],
@@ -1221,93 +1287,63 @@ def initToolbar(self):
)
self.theme_action.setCheckable(True)
self.theme_action.setChecked(settings.value("appTheme") == "dark")
-
self.ui_toolbar.addAction(self.theme_action)
+
self.powersaveraction = QAction(
- translations[lang]["powersaver"],
- self,
- checkable=True,
+ translations[lang]["powersaver"], self, checkable=True
)
self.powersaveraction.setStatusTip(translations[lang]["powersaver_message"])
self.powersaveraction.toggled.connect(self.hybridSaver)
-
self.ui_toolbar.addAction(self.powersaveraction)
+
adaptiveResponse = settings.value(
"adaptiveResponse", fallbackValues["adaptiveResponse"]
)
self.powersaveraction.setChecked(adaptiveResponse > 1)
- self.ui_toolbar.addAction(self.powersaveraction)
self.hide_ai_dock = self.createAction(
- "AI",
- "AI",
- self.toggleDock,
- QKeySequence("Ctrl+Shift+D"),
- "",
+ "AI", "AI", self.toggleDock, QKeySequence("Ctrl+Shift+D"), ""
)
self.ui_toolbar.addAction(self.hide_ai_dock)
self.ui_toolbar.addAction(self.helpAction)
self.ui_toolbar.addAction(self.aboutAction)
+
self.language_combobox = QComboBox(self)
self.language_combobox.setStyleSheet("background-color:#000000; color:#FFFFFF;")
for lcid, name in languages.items():
self.language_combobox.addItem(name, lcid)
-
self.language_combobox.currentIndexChanged.connect(self.changeLanguage)
self.ui_toolbar.addWidget(self.language_combobox)
self.addToolBarBreak()
- self.edit_toolbar = self.addToolBar(translations[lang]["edit"])
- self.toolbarLabel(
- self.edit_toolbar,
- translations[lang]["edit"] + ": ",
- )
- self.edit_toolbar.addActions(
- [
- self.alignrightevent,
- self.aligncenterevent,
- self.alignleftevent,
- self.alignjustifiedevent,
- ]
- )
- self.edit_toolbar.addSeparator()
- self.font_toolbar = self.addToolBar(translations[lang]["font"])
- self.toolbarLabel(
- self.font_toolbar,
- translations[lang]["font"] + ": ",
- )
- self.font_toolbar.addActions([self.bold, self.italic, self.underline])
- self.font_toolbar.addSeparator()
- self.list_toolbar = self.addToolBar(translations[lang]["list"])
- self.toolbarLabel(
- self.list_toolbar,
- translations[lang]["list"] + ": ",
- )
- self.list_toolbar.addActions([self.bulletevent, self.numberedevent])
+ edit_actions = [
+ self.alignrightevent,
+ self.aligncenterevent,
+ self.alignleftevent,
+ self.alignjustifiedevent,
+ ]
+ self.edit_toolbar = add_toolbar("edit", edit_actions)
+
+ font_actions = [self.bold, self.italic, self.underline]
+ self.font_toolbar = add_toolbar("font", font_actions)
+
+ list_actions = [self.bulletevent, self.numberedevent]
+ self.list_toolbar = add_toolbar("list", list_actions)
+
self.addToolBarBreak()
- self.color_toolbar = self.addToolBar(translations[lang]["color"])
- self.toolbarLabel(
- self.color_toolbar,
- translations[lang]["color"] + ": ",
- )
- self.color_toolbar.addActions(
- [
- self.color,
- self.backgroundcolor,
- self.fontfamily,
- self.inc_fontaction,
- self.dec_fontaction,
- ]
- )
+ color_actions = [
+ self.color,
+ self.backgroundcolor,
+ self.fontfamily,
+ self.inc_fontaction,
+ self.dec_fontaction,
+ ]
+ self.color_toolbar = add_toolbar("color", color_actions)
- self.multimedia_toolbar = self.addToolBar(translations[lang]["multimedia"])
- self.toolbarLabel(
- self.multimedia_toolbar,
- translations[lang]["multimedia"] + ": ",
- )
- self.multimedia_toolbar.addActions([self.addimage])
+ multimedia_actions = [self.addimage]
+ self.multimedia_toolbar = add_toolbar("multimedia", multimedia_actions)
def toggleDock(self):
if self.ai_widget.isHidden():
@@ -1322,13 +1358,13 @@ def hybridSaver(self, checked):
if battery:
if battery.percent <= 35 and not battery.power_plugged:
# Ultra
- self.adaptiveResponse = 12
+ self.adaptiveResponse = 6
else:
# Standard
- self.adaptiveResponse = 6
+ self.adaptiveResponse = 4
else:
# Global Standard
- self.adaptiveResponse = 3
+ self.adaptiveResponse = 2
else:
self.adaptiveResponse = fallbackValues["adaptiveResponse"]
@@ -1345,20 +1381,23 @@ def detectEncoding(file_path):
detector.close()
return detector.result["encoding"]
+ def resetDocumentArea(self):
+ self.DocumentArea.clear()
+ self.DocumentArea.setFontFamily(fallbackValues["fontFamily"])
+ self.DocumentArea.setFontPointSize(fallbackValues["fontSize"])
+ self.DocumentArea.setFontWeight(75 if fallbackValues["bold"] else 50)
+ self.DocumentArea.setFontItalic(fallbackValues["italic"])
+ self.DocumentArea.setFontUnderline(fallbackValues["underline"])
+ self.DocumentArea.setAlignment(fallbackValues["contentAlign"])
+ self.DocumentArea.setTextColor(QColor(fallbackValues["contentColor"]))
+ self.DocumentArea.setTextBackgroundColor(
+ QColor(fallbackValues["contentBackgroundColor"])
+ )
+ self.DocumentArea.setTabStopDistance(27)
+
def newFile(self):
- if self.is_saved == True:
- self.DocumentArea.clear()
- self.DocumentArea.setFontFamily(fallbackValues["fontFamily"])
- self.DocumentArea.setFontPointSize(fallbackValues["fontSize"])
- self.DocumentArea.setFontWeight(75 if fallbackValues["bold"] else 50)
- self.DocumentArea.setFontItalic(fallbackValues["italic"])
- self.DocumentArea.setFontUnderline(fallbackValues["underline"])
- self.DocumentArea.setAlignment(fallbackValues["contentAlign"])
- self.DocumentArea.setTextColor(QColor(fallbackValues["contentColor"]))
- self.DocumentArea.setTextBackgroundColor(
- QColor(fallbackValues["contentBackgroundColor"])
- )
- self.DocumentArea.setTabStopDistance(27)
+ if self.is_saved:
+ self.resetDocumentArea()
self.directory = self.default_directory
self.file_name = None
self.is_saved = False
@@ -1373,24 +1412,7 @@ def newFile(self):
)
if reply == QMessageBox.Yes:
- self.DocumentArea.clear()
- self.DocumentArea.setFontFamily(fallbackValues["fontFamily"])
- self.DocumentArea.setFontPointSize(fallbackValues["fontSize"])
- self.DocumentArea.setFontWeight(75 if fallbackValues["bold"] else 50)
- self.DocumentArea.setFontItalic(fallbackValues["italic"])
- self.DocumentArea.setFontUnderline(fallbackValues["underline"])
- self.DocumentArea.setAlignment(fallbackValues["contentAlign"])
- self.DocumentArea.setTextColor(QColor(fallbackValues["contentColor"]))
- self.DocumentArea.setTextBackgroundColor(
- QColor(fallbackValues["contentBackgroundColor"])
- )
- self.DocumentArea.setTabStopDistance(27)
- self.directory = self.default_directory
- self.file_name = None
- self.is_saved = False
- self.updateTitle()
- else:
- pass
+ self.resetDocumentArea()
def openFile(self, file_to_open=None):
options = QFileDialog.Options()
@@ -1531,27 +1553,43 @@ def viewHelp(self):
def bulletList(self):
cursor = self.DocumentArea.textCursor()
cursor.beginEditBlock()
+
selected_text = cursor.selectedText()
+ lines = selected_text.split("\n")
char_format = cursor.charFormat()
- cursor.removeSelectedText()
- cursor.insertList(QTextListFormat.ListDisc)
- cursor.insertText(selected_text)
- new_cursor = self.DocumentArea.textCursor()
- new_cursor.movePosition(QTextCursor.PreviousBlock)
- new_cursor.mergeCharFormat(char_format)
+
+ for line in lines:
+ if line.strip():
+ cursor.insertList(QTextListFormat.ListDisc)
+ cursor.insertText(line)
+ cursor.insertBlock()
+ else:
+ cursor.insertBlock()
+
+ cursor.mergeCharFormat(char_format)
+
cursor.endEditBlock()
def numberedList(self):
cursor = self.DocumentArea.textCursor()
cursor.beginEditBlock()
+
selected_text = cursor.selectedText()
+
+ lines = selected_text.split("\n")
+
char_format = cursor.charFormat()
- cursor.removeSelectedText()
- cursor.insertList(QTextListFormat.ListDecimal)
- cursor.insertText(selected_text)
- new_cursor = self.DocumentArea.textCursor()
- new_cursor.movePosition(QTextCursor.PreviousBlock)
- new_cursor.mergeCharFormat(char_format)
+
+ for line in lines:
+ if line.strip():
+ cursor.insertList(QTextListFormat.ListDecimal)
+ cursor.insertText(line)
+ cursor.insertBlock()
+ else:
+ cursor.insertBlock()
+
+ cursor.mergeCharFormat(char_format)
+
cursor.endEditBlock()
def contentAlign(self, alignment):
@@ -1603,11 +1641,10 @@ def decFont(self):
def find(self):
self.find_dialog = QInputDialog(self)
self.find_dialog.setInputMode(QInputDialog.TextInput)
- app_language = lang
- self.find_dialog.setLabelText(translations[app_language]["find"])
- self.find_dialog.setWindowTitle(translations[app_language]["find"])
- self.find_dialog.setOkButtonText(translations[app_language]["find"])
- self.find_dialog.setCancelButtonText(translations[app_language]["cancel"])
+ self.find_dialog.setLabelText(translations[lang]["find"])
+ self.find_dialog.setWindowTitle(translations[lang]["find"])
+ self.find_dialog.setOkButtonText(translations[lang]["find"])
+ self.find_dialog.setCancelButtonText(translations[lang]["cancel"])
self.find_dialog.textValueSelected.connect(self.findText)
self.find_dialog.show()
@@ -1639,7 +1676,7 @@ def replaceText(self, text):
app.setOrganizationName("berkaygediz")
app.setApplicationName("SolidWriting")
app.setApplicationDisplayName("SolidWriting 2025.02")
- app.setApplicationVersion("1.5.2025.02-1")
+ app.setApplicationVersion("1.5.2025.02-2")
ws = SW_ControlInfo()
ws.show()
sys.exit(app.exec())
diff --git a/file_version_info.txt b/file_version_info.txt
index 43400a2..911a64c 100644
--- a/file_version_info.txt
+++ b/file_version_info.txt
@@ -31,13 +31,13 @@ VSVersionInfo(
StringTable(
u'040904B0',
[StringStruct(u'CompanyName', u'berkaygediz'),
- StringStruct(u'FileDescription', u'Real-time computing and formatting supported word processor.'),
- StringStruct(u'FileVersion', u'1.5.2024.11'),
+ StringStruct(u'FileDescription', u'A supercharged word processor with AI integration, supporting real-time computing and advanced formatting.'),
+ StringStruct(u'FileVersion', u'1.5.2025.02'),
StringStruct(u'InternalName', u'SolidWriting'),
- StringStruct(u'LegalCopyright', u'2024 © berkaygediz. All rights reserved.'),
+ StringStruct(u'LegalCopyright', u'2025 © berkaygediz. All rights reserved.'),
StringStruct(u'OriginalFilename', u'SolidWriting.exe'),
StringStruct(u'ProductName', u'SolidWriting'),
- StringStruct(u'ProductVersion', u'1.5.2024.11')])
+ StringStruct(u'ProductVersion', u'1.5.2025.02')])
]),
VarFileInfo([VarStruct(u'Translation', [1033, 1200])])
]
diff --git a/metadata.yml b/metadata.yml
index 10f0e79..e001329 100644
--- a/metadata.yml
+++ b/metadata.yml
@@ -1,6 +1,6 @@
Version: 1.4.2025.02
CompanyName: berkaygediz
-FileDescription: Real-time computing and formatting supported word processor.
+FileDescription: A supercharged word processor with AI integration, supporting real-time computing and advanced formatting.
InternalName: SolidWriting
LegalCopyright: 2025 © berkaygediz. All rights reserved.
OriginalFilename: SolidWriting.exe
diff --git a/requirements.txt b/requirements.txt
index 3134a53..3348f6f 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -1,8 +1,8 @@
-PySide6==6.7.2
-mammoth==1.8.0
+PySide6==6.8.2.1
+mammoth==1.9.0
chardet==5.2.0
-psutil==6.0.0
+psutil==7.0.0
langdetect==1.0.9
-pyinstaller==6.10.0
+pyinstaller==6.12.0
llama-cpp-python==0.3.1
-torch==2.5.1
\ No newline at end of file
+torch==2.6.0
\ No newline at end of file
diff --git a/version.rc b/version.rc
new file mode 100644
index 0000000..b277cfa
--- /dev/null
+++ b/version.rc
@@ -0,0 +1,30 @@
+#include
+
+VS_VERSION_INFO VERSIONINFO
+FILEVERSION 1, 5, 2025, 02
+PRODUCTVERSION 1, 5, 2025, 02
+FILEFLAGSMASK VS_FFI_FILEFLAGSMASK
+FILEFLAGS VS_FILEFLAG_RELEASE
+FILEOS VOS_NT_WINDOWS32
+FILETYPE VFT_APP
+FILESUBTYPE VFT2_UNKNOWN
+BEGIN
+ BLOCK "StringFileInfo"
+ BEGIN
+ BLOCK "040904b0"
+ BEGIN
+ VALUE "CompanyName", "berkaygediz"
+ VALUE "FileDescription", "A supercharged word processor with AI integration, supporting real-time computing and advanced formatting."
+ VALUE "FileVersion", "1.5.2025.02"
+ VALUE "InternalName", "SolidWriting"
+ VALUE "LegalCopyright", "Copyright (C) 2025 berkaygediz"
+ VALUE "OriginalFilename", "SolidWriting.exe"
+ VALUE "ProductName", "SolidWriting"
+ VALUE "ProductVersion", "1.5.2025.02"
+ END
+ END
+ BLOCK "VarFileInfo"
+ BEGIN
+ VALUE "Translation", 0x409, 1200
+ END
+END