add new LLM provider io.net gemini g4f
This commit is contained in:
@@ -1,36 +1,36 @@
|
||||
import re
|
||||
from pylatexenc.latex2text import LatexNodes2Text
|
||||
from markdown_pdf import MarkdownPdf
|
||||
from markdown_pdf import Section
|
||||
|
||||
class ConvertMdToPdf:
|
||||
# Конвертирует md в pdf
|
||||
def convertLatexToText(self, text:str):
|
||||
'''
|
||||
Функция для конвертации LaTeX в текст;
|
||||
|
||||
Args:
|
||||
:param text: текст содержащий LaTeX.
|
||||
'''
|
||||
|
||||
# Обрабатываем только математические выражения
|
||||
text = re.sub(
|
||||
r'\$\$(.*?)\$\$|\$(.*?)\$',
|
||||
self.replace_math,
|
||||
text,
|
||||
flags=re.DOTALL
|
||||
)
|
||||
pdf = MarkdownPdf(toc_level=0, optimize=True)
|
||||
pdf.add_section(Section(text))
|
||||
return pdf, text
|
||||
|
||||
def replace_math(self, match):
|
||||
math_content = match.group(1) or match.group(2) # $$...$$ или $...$
|
||||
try:
|
||||
# Преобразуем только математическое выражение
|
||||
converted = LatexNodes2Text().latex_to_text(math_content)
|
||||
|
||||
return converted
|
||||
except:
|
||||
return math_content # В случае ошибки оставляем как есть
|
||||
|
||||
import re
|
||||
from pylatexenc.latex2text import LatexNodes2Text
|
||||
from markdown_pdf import MarkdownPdf
|
||||
from markdown_pdf import Section
|
||||
|
||||
class ConvertMdToPdf:
|
||||
# Конвертирует md в pdf
|
||||
def convertLatexToText(self, text:str):
|
||||
'''
|
||||
Функция для конвертации LaTeX в текст;
|
||||
|
||||
Args:
|
||||
:param text: текст содержащий LaTeX.
|
||||
'''
|
||||
|
||||
# Обрабатываем только математические выражения
|
||||
text = re.sub(
|
||||
r'\$\$(.*?)\$\$|\$(.*?)\$',
|
||||
self.replace_math,
|
||||
text,
|
||||
flags=re.DOTALL
|
||||
)
|
||||
pdf = MarkdownPdf(toc_level=0, optimize=True)
|
||||
pdf.add_section(Section(text))
|
||||
return pdf, text
|
||||
|
||||
def replace_math(self, match):
|
||||
math_content = match.group(1) or match.group(2) # $$...$$ или $...$
|
||||
try:
|
||||
# Преобразуем только математическое выражение
|
||||
converted = LatexNodes2Text().latex_to_text(math_content)
|
||||
|
||||
return converted
|
||||
except:
|
||||
return math_content # В случае ошибки оставляем как есть
|
||||
|
||||
|
||||
@@ -1,31 +1,31 @@
|
||||
from pathlib import Path
|
||||
|
||||
# Для аннотации типов
|
||||
from markdown_pdf import MarkdownPdf
|
||||
from pydub import AudioSegment
|
||||
|
||||
class FileHandlers:
|
||||
# Функция сохранения файла
|
||||
def saveFile(self, filename, content, output_path, format='mp3'):
|
||||
'''
|
||||
Сохраняет текст, pdf из markdown_pdf или склеенный аудиофайл в файл с указанным названием и директорией.
|
||||
|
||||
Args:
|
||||
:param filename: название файла;
|
||||
:param content: содержание файла;
|
||||
:param output_path: выходная диретория файла.
|
||||
'''
|
||||
# Создание объекта директории
|
||||
directory = Path(output_path)
|
||||
filePath = directory / filename # Добавление пути директории
|
||||
filePath.parent.mkdir(parents=True, exist_ok=True) # Создание директории если не существует
|
||||
|
||||
# Сохранение для разных типов
|
||||
if type(content) == MarkdownPdf:
|
||||
return content.save(filePath)
|
||||
|
||||
elif type(content) == str:
|
||||
return filePath.write_text(content, encoding='utf-8')
|
||||
|
||||
elif type(content) == AudioSegment:
|
||||
return content.export(filePath, format=format)
|
||||
from pathlib import Path
|
||||
|
||||
# Для аннотации типов
|
||||
from markdown_pdf import MarkdownPdf
|
||||
from pydub import AudioSegment
|
||||
|
||||
class FileHandlers:
|
||||
# Функция сохранения файла
|
||||
def saveFile(self, filename, content, output_path, format='mp3'):
|
||||
'''
|
||||
Сохраняет текст, pdf из markdown_pdf или склеенный аудиофайл в файл с указанным названием и директорией.
|
||||
|
||||
Args:
|
||||
:param filename: название файла;
|
||||
:param content: содержание файла;
|
||||
:param output_path: выходная диретория файла.
|
||||
'''
|
||||
# Создание объекта директории
|
||||
directory = Path(output_path)
|
||||
filePath = directory / filename # Добавление пути директории
|
||||
filePath.parent.mkdir(parents=True, exist_ok=True) # Создание директории если не существует
|
||||
|
||||
# Сохранение для разных типов
|
||||
if type(content) == MarkdownPdf:
|
||||
return content.save(filePath)
|
||||
|
||||
elif type(content) == str:
|
||||
return filePath.write_text(content, encoding='utf-8')
|
||||
|
||||
elif type(content) == AudioSegment:
|
||||
return content.export(filePath, format=format)
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
from pydub import AudioSegment
|
||||
|
||||
class GlueAudio():
|
||||
def glue(self, audioFiles):
|
||||
glued = AudioSegment.empty()
|
||||
|
||||
for audioFile in audioFiles:
|
||||
audio = AudioSegment.from_file(audioFile)
|
||||
glued += audio
|
||||
|
||||
return glued
|
||||
from pydub import AudioSegment
|
||||
|
||||
class GlueAudio():
|
||||
def glue(self, audioFiles):
|
||||
glued = AudioSegment.empty()
|
||||
|
||||
for audioFile in audioFiles:
|
||||
audio = AudioSegment.from_file(audioFile)
|
||||
glued += audio
|
||||
|
||||
return glued
|
||||
|
||||
@@ -1,62 +1,67 @@
|
||||
class GradioHandlers:
|
||||
def __init__(self, gr, Llm, ConvertMdToPdf, FileHandlers, FasterWhisper, GlueAudio):
|
||||
# Объект для работы с файлами
|
||||
self.fh = FileHandlers()
|
||||
self.ga = GlueAudio()
|
||||
self.ConvertMdToPdf = ConvertMdToPdf()
|
||||
self.FasterWhisper = FasterWhisper()
|
||||
self.Llm = Llm
|
||||
self.gr = gr
|
||||
|
||||
def handleRecognizeBtn(self, audioFiles, model, device, compute_type, beamSize, vadFilter, minSilenceDurationMs, speechPadMs, temp0, temp1, temp2, wordTimestamps, noSpeechThreshold, conditionOnPreviousText, filename, outPath):
|
||||
audioFile = self.ga.glue(audioFiles)
|
||||
file = self.fh.saveFile(filename, audioFile, outPath)
|
||||
|
||||
return self.FasterWhisper.recognize(model, device, compute_type, file, beamSize, vadFilter, minSilenceDurationMs, speechPadMs, temp0, temp1, temp2, wordTimestamps, noSpeechThreshold, conditionOnPreviousText)
|
||||
|
||||
# Функция улучшения текста
|
||||
def generateByCondition(self, api_key, llm_model, system_prompt, recognized_text, llm_temperature, is_pipeline_enabled, trigger, isSaveFile, filename, filenamePdf, output_path):
|
||||
llm = self.Llm(api_key)
|
||||
|
||||
# если чекбокс включен и событие было change → обрабатываем
|
||||
if is_pipeline_enabled and trigger == "change":
|
||||
result, md = llm.generate(llm_model, system_prompt, recognized_text, llm_temperature)
|
||||
|
||||
# Конвертируем текст с латексом в юникод
|
||||
pdf, unicodeText = self.ConvertMdToPdf.convertLatexToText(md)
|
||||
|
||||
if isSaveFile:
|
||||
self.fh.saveFile(filenamePdf, pdf, output_path)
|
||||
self.fh.saveFile(filename, result, output_path)
|
||||
|
||||
return result, unicodeText
|
||||
|
||||
# если чекбокс выключен и событие было click → обрабатываем
|
||||
if not is_pipeline_enabled and trigger == "click":
|
||||
result, md = llm.generate(llm_model, system_prompt, recognized_text, llm_temperature)
|
||||
|
||||
# Конвертируем текст с латексом в юникод
|
||||
pdf, unicodeText = self.ConvertMdToPdf.convertLatexToText(md)
|
||||
|
||||
if isSaveFile:
|
||||
self.fh.saveFile(filenamePdf, pdf, output_path)
|
||||
self.fh.saveFile(filename, result, output_path)
|
||||
|
||||
return result, unicodeText
|
||||
|
||||
# если нет чекбокса и было событие change
|
||||
return self.gr.skip(), self.gr.skip()
|
||||
|
||||
# Функция для динамического обновления кнопки в зависимости от состояния checkbox
|
||||
def updateButton(self, isChecked):
|
||||
if not isChecked:
|
||||
variant = 'primary'
|
||||
else:
|
||||
variant = 'secondary'
|
||||
|
||||
return self.gr.update(interactive=not isChecked, variant=variant)
|
||||
|
||||
|
||||
def updateTextbox(self, isChecked):
|
||||
return self.gr.update(visible=isChecked)
|
||||
|
||||
from config import LLM_MODELS # Импортируем словарь моделей
|
||||
import gradio as gr
|
||||
|
||||
|
||||
class GradioHandlers:
|
||||
def __init__(self, llm_factory, ConvertMdToPdf, FileHandlers, FasterWhisper, GlueAudio):
|
||||
# Объект для работы с файлами
|
||||
self.fh = FileHandlers()
|
||||
self.ga = GlueAudio()
|
||||
self.ConvertMdToPdf = ConvertMdToPdf()
|
||||
self.FasterWhisper = FasterWhisper()
|
||||
self.llm_factory = llm_factory # Сохраняем фабрику
|
||||
|
||||
def handleRecognizeBtn(self, audioFiles, model, device, compute_type, beamSize, vadFilter, minSilenceDurationMs, speechPadMs, temp0, temp1, temp2, wordTimestamps, noSpeechThreshold, conditionOnPreviousText, filename, outPath):
|
||||
audioFile = self.ga.glue(audioFiles)
|
||||
file = self.fh.saveFile(filename, audioFile, outPath)
|
||||
|
||||
return self.FasterWhisper.recognize(model, device, compute_type, file, beamSize, vadFilter, minSilenceDurationMs, speechPadMs, temp0, temp1, temp2, wordTimestamps, noSpeechThreshold, conditionOnPreviousText)
|
||||
|
||||
# Функция улучшения текста
|
||||
def generateByCondition(self, api_key, llm_provider, llm_model, system_prompt, recognized_text, llm_temperature, is_pipeline_enabled, trigger, isSaveFile, filename, filenamePdf, output_path):
|
||||
try:
|
||||
# Получаем нужный провайдер через фабрику
|
||||
provider = self.llm_factory(llm_provider, api_key)
|
||||
except ValueError as e:
|
||||
# Если API ключ не предоставлен для нужного провайдера, выводим ошибку
|
||||
self.gr.Warning(str(e))
|
||||
return self.gr.skip(), self.gr.skip()
|
||||
|
||||
def process():
|
||||
result, md = provider.generate(llm_model, system_prompt, recognized_text, llm_temperature)
|
||||
pdf, unicodeText = self.ConvertMdToPdf.convertLatexToText(md)
|
||||
if isSaveFile:
|
||||
self.fh.saveFile(filenamePdf, pdf, output_path)
|
||||
self.fh.saveFile(filename, result, output_path)
|
||||
return result, unicodeText
|
||||
|
||||
if (is_pipeline_enabled and trigger == "change") or (not is_pipeline_enabled and trigger == "click"):
|
||||
return process()
|
||||
|
||||
return gr.skip(), gr.skip()
|
||||
|
||||
# НОВАЯ ФУНКЦИЯ для обновления списка моделей
|
||||
def update_model_dropdown(self, provider):
|
||||
"""
|
||||
Вызывается при изменении llmProvider.
|
||||
Возвращает обновленный компонент Dropdown для моделей.
|
||||
"""
|
||||
# Получаем список моделей для выбранного провайдера
|
||||
models = LLM_MODELS.get(provider, [])
|
||||
|
||||
# Выбираем первое значение по умолчанию, если список не пуст
|
||||
default_value = models[0] if models else None
|
||||
|
||||
# Возвращаем обновленный компонент. Используем 'gr' напрямую.
|
||||
return gr.update(choices=models, value=default_value)
|
||||
|
||||
# Функция для динамического обновления кнопки
|
||||
def updateButton(self, isChecked):
|
||||
if not isChecked:
|
||||
variant = 'primary'
|
||||
else:
|
||||
variant = 'secondary'
|
||||
return gr.update(interactive=not isChecked, variant=variant)
|
||||
|
||||
def updateTextbox(self, isChecked):
|
||||
return gr.update(visible=isChecked)
|
||||
Reference in New Issue
Block a user