add new LLM provider io.net gemini g4f
This commit is contained in:
@@ -1,34 +1,34 @@
|
||||
from faster_whisper import WhisperModel
|
||||
|
||||
class FasterWhisper:
|
||||
def recognize(self, model, device, compute_type, audioFile, beamSize, vadFilter, minSilenceDurationMs, speechPadMs, temp0, temp1, temp2, wordTimestamps, noSpeechThreshold, conditionOnPreviousText):
|
||||
model = WhisperModel(model, device=device, compute_type=compute_type) # Задаем модель
|
||||
|
||||
segments, _ = model.transcribe( # Распознаем текст
|
||||
audioFile,
|
||||
beam_size=beamSize,
|
||||
vad_filter=vadFilter,
|
||||
vad_parameters={
|
||||
"min_silence_duration_ms": minSilenceDurationMs,
|
||||
"speech_pad_ms": speechPadMs
|
||||
},
|
||||
temperature= [temp0, temp1, temp2],
|
||||
word_timestamps=wordTimestamps,
|
||||
no_speech_threshold=noSpeechThreshold,
|
||||
condition_on_previous_text=conditionOnPreviousText
|
||||
)
|
||||
|
||||
text = ''
|
||||
|
||||
for seg in segments:
|
||||
text += f"[{self.format_timestamp(seg.start)} -> {self.format_timestamp(seg.end)}] {seg.text}" + '\n'
|
||||
|
||||
return text
|
||||
|
||||
def format_timestamp(self, seconds: float) -> str:
|
||||
millis = int(seconds * 1000)
|
||||
hours = millis // (3600 * 1000)
|
||||
minutes = (millis % (3600 * 1000)) // (60 * 1000)
|
||||
seconds_int = (millis % (60 * 1000)) // 1000
|
||||
millis = millis % 1000
|
||||
return f"{hours:02d}:{minutes:02d}:{seconds_int:02d},{millis:03d}"
|
||||
from faster_whisper import WhisperModel
|
||||
|
||||
class FasterWhisper:
|
||||
def recognize(self, model, device, compute_type, audioFile, beamSize, vadFilter, minSilenceDurationMs, speechPadMs, temp0, temp1, temp2, wordTimestamps, noSpeechThreshold, conditionOnPreviousText):
|
||||
model = WhisperModel(model, device=device, compute_type=compute_type) # Задаем модель
|
||||
|
||||
segments, _ = model.transcribe( # Распознаем текст
|
||||
audioFile,
|
||||
beam_size=beamSize,
|
||||
vad_filter=vadFilter,
|
||||
vad_parameters={
|
||||
"min_silence_duration_ms": minSilenceDurationMs,
|
||||
"speech_pad_ms": speechPadMs
|
||||
},
|
||||
temperature= [temp0, temp1, temp2],
|
||||
word_timestamps=wordTimestamps,
|
||||
no_speech_threshold=noSpeechThreshold,
|
||||
condition_on_previous_text=conditionOnPreviousText
|
||||
)
|
||||
|
||||
text = ''
|
||||
|
||||
for seg in segments:
|
||||
text += f"[{self.format_timestamp(seg.start)} -> {self.format_timestamp(seg.end)}] {seg.text}" + '\n'
|
||||
|
||||
return text
|
||||
|
||||
def format_timestamp(self, seconds: float) -> str:
|
||||
millis = int(seconds * 1000)
|
||||
hours = millis // (3600 * 1000)
|
||||
minutes = (millis % (3600 * 1000)) // (60 * 1000)
|
||||
seconds_int = (millis % (60 * 1000)) // 1000
|
||||
millis = millis % 1000
|
||||
return f"{hours:02d}:{minutes:02d}:{seconds_int:02d},{millis:03d}"
|
||||
|
||||
@@ -1,36 +0,0 @@
|
||||
import openai
|
||||
|
||||
class Llm:
|
||||
def __init__(self, apiKey:str):
|
||||
self.client = openai.OpenAI(
|
||||
api_key=apiKey,
|
||||
base_url='https://api.intelligence.io.solutions/api/v1/'
|
||||
)
|
||||
|
||||
def generate(self, model:str, systemPrompt:str, userPrompt:str, temp:float):
|
||||
'''
|
||||
Функция для генирации текста по промпту.
|
||||
|
||||
Args:
|
||||
:param model: модель llm;
|
||||
:param systemPrompt: системный промпт;
|
||||
:param userPrompt: основной промпт промпт;
|
||||
:param temp: температура генерации.
|
||||
'''
|
||||
|
||||
# Получаем ответ от нейросети
|
||||
response = self.client.chat.completions.create(
|
||||
model=model,
|
||||
messages=[
|
||||
{'role': 'system', 'content': systemPrompt},
|
||||
{'role': 'user', 'content': userPrompt},
|
||||
],
|
||||
temperature=temp,
|
||||
stream=False
|
||||
)
|
||||
|
||||
# Достаем текст
|
||||
text = str(response.choices[0].message.content)
|
||||
|
||||
return text, text
|
||||
|
||||
22
services/llm_factory.py
Normal file
22
services/llm_factory.py
Normal file
@@ -0,0 +1,22 @@
|
||||
# services/llm_factory.py
|
||||
from services.llm_providers.ionet_provider import IoNetProvider
|
||||
from services.llm_providers.gemini_provider import GeminiProvider
|
||||
from services.llm_providers.gpt4free_provider import Gpt4FreeProvider
|
||||
from services.llm_providers.base_provider import BaseLLMProvider
|
||||
|
||||
def get_llm_provider(provider_name: str, api_key: str | None) -> BaseLLMProvider:
|
||||
"""
|
||||
Фабричная функция для получения экземпляра провайдера LLM.
|
||||
"""
|
||||
if provider_name == 'io.net':
|
||||
if not api_key:
|
||||
raise ValueError("API ключ обязателен для io.net")
|
||||
return IoNetProvider(api_key)
|
||||
elif provider_name == 'Gemini':
|
||||
if not api_key:
|
||||
raise ValueError("API ключ обязателен для Gemini")
|
||||
return GeminiProvider(api_key)
|
||||
elif provider_name == 'gpt4free':
|
||||
return Gpt4FreeProvider()
|
||||
else:
|
||||
raise ValueError(f"Неизвестный провайдер: {provider_name}")
|
||||
18
services/llm_providers/base_provider.py
Normal file
18
services/llm_providers/base_provider.py
Normal file
@@ -0,0 +1,18 @@
|
||||
from abc import ABC, abstractmethod
|
||||
|
||||
class BaseLLMProvider(ABC):
|
||||
"""
|
||||
Абстрактный базовый класс для всех провайдеров LLM.
|
||||
Каждый провайдер должен реализовать метод generate.
|
||||
"""
|
||||
def __init__(self, api_key: str | None = None):
|
||||
self.api_key = api_key
|
||||
|
||||
@abstractmethod
|
||||
def generate(self, model: str, system_prompt: str, user_prompt: str, temp: float):
|
||||
"""
|
||||
Основной метод для генерации текста.
|
||||
|
||||
Должен возвращать кортеж из двух строк: (чистый_текст, markdown_текст)
|
||||
"""
|
||||
pass
|
||||
74
services/llm_providers/gemini_provider.py
Normal file
74
services/llm_providers/gemini_provider.py
Normal file
@@ -0,0 +1,74 @@
|
||||
# services/llm_providers/gemini_provider.py
|
||||
|
||||
import requests
|
||||
from .base_provider import BaseLLMProvider
|
||||
|
||||
class GeminiProvider(BaseLLMProvider):
|
||||
"""
|
||||
Провайдер для Google Gemini, использующий прямые REST API вызовы
|
||||
через библиотеку requests для надежной работы с SOCKS-прокси.
|
||||
"""
|
||||
def __init__(self, api_key: str):
|
||||
super().__init__(api_key)
|
||||
self.base_url = "https://generativelanguage.googleapis.com/v1beta/models/"
|
||||
|
||||
def generate(self, model: str, system_prompt: str, user_prompt: str, temp: float):
|
||||
"""
|
||||
Генерирует текст с помощью модели Gemini, отправляя запрос через прокси.
|
||||
"""
|
||||
# 1. Формируем URL для запроса
|
||||
api_url = f"{self.base_url}{model}:generateContent?key={self.api_key}"
|
||||
|
||||
# 2. Задаем настройки прокси из вашего примера
|
||||
# socks5h:// означает, что DNS-запросы также будут идти через прокси
|
||||
proxies = {
|
||||
'http': 'socks5://192.168.1.6:2080',
|
||||
'https': 'socks5h://192.168.1.6:2080'
|
||||
}
|
||||
|
||||
# 3. Собираем тело запроса (payload) в формате, который ожидает Gemini API
|
||||
data = {
|
||||
"system_instruction": {
|
||||
"parts": {"text": system_prompt}
|
||||
},
|
||||
"contents": [{
|
||||
"parts": [{"text": user_prompt}]
|
||||
}],
|
||||
"generationConfig": {
|
||||
"temperature": temp
|
||||
}
|
||||
}
|
||||
|
||||
try:
|
||||
# 4. Отправляем POST-запрос с данными и настройками прокси
|
||||
response = requests.post(api_url, json=data, proxies=proxies, timeout=90)
|
||||
|
||||
# Проверяем, не вернул ли сервер ошибку (например, 4xx или 5xx)
|
||||
response.raise_for_status()
|
||||
|
||||
# 5. Парсим JSON-ответ и извлекаем сгенерированный текст
|
||||
response_json = response.json()
|
||||
|
||||
# Добавим проверку на случай, если контент был заблокирован
|
||||
if "candidates" not in response_json or not response_json["candidates"]:
|
||||
block_reason = response_json.get("promptFeedback", {}).get("blockReason", "неизвестная причина")
|
||||
error_message = f"Контент заблокирован. Причина: {block_reason}"
|
||||
return error_message, error_message
|
||||
|
||||
text = response_json["candidates"][0]["content"]["parts"][0]["text"]
|
||||
return text, text
|
||||
|
||||
except requests.exceptions.ProxyError as e:
|
||||
error_message = f"Ошибка подключения к прокси. Убедитесь, что Nekobox запущен и слушает порт 2080. Ошибка: {e}"
|
||||
print(error_message)
|
||||
return error_message, error_message
|
||||
except requests.exceptions.RequestException as e:
|
||||
# Ловим все остальные ошибки requests (таймаут, проблемы с сетью и т.д.)
|
||||
error_message = f"Произошла ошибка при обращении к API Gemini: {e}"
|
||||
print(error_message)
|
||||
return error_message, error_message
|
||||
except (KeyError, IndexError) as e:
|
||||
# Ловим ошибки, если структура JSON-ответа неожиданная
|
||||
error_message = f"Не удалось разобрать ответ от API Gemini. Структура ответа изменилась. Ошибка: {e}"
|
||||
print(error_message)
|
||||
return error_message, error_message
|
||||
28
services/llm_providers/gpt4free_provider.py
Normal file
28
services/llm_providers/gpt4free_provider.py
Normal file
@@ -0,0 +1,28 @@
|
||||
# services/llm_providers/gpt4free_provider.py
|
||||
from g4f.client import Client
|
||||
from .base_provider import BaseLLMProvider
|
||||
|
||||
class Gpt4FreeProvider(BaseLLMProvider):
|
||||
# gpt4free не требует API ключа
|
||||
def __init__(self, api_key: str | None = None):
|
||||
super().__init__(api_key)
|
||||
self.client = Client()
|
||||
|
||||
|
||||
def generate(self, model: str, system_prompt: str, user_prompt: str, temp: float):
|
||||
# temp в g4f может работать не для всех внутренних провайдеров
|
||||
try:
|
||||
response = self.client.chat.completions.create(
|
||||
model=model, # Пример модели, может варьироваться в зависимости от доступности провайдеров
|
||||
messages=[
|
||||
{"role": "system", "content": system_prompt},
|
||||
{"role": "user", "content": user_prompt}
|
||||
],
|
||||
temperature=temp
|
||||
)
|
||||
text = response.choices[0].message.content
|
||||
return text, text
|
||||
except Exception as e:
|
||||
error_message = f"Ошибка при работе с gpt4free: {e}"
|
||||
print(error_message)
|
||||
return error_message, error_message
|
||||
23
services/llm_providers/ionet_provider.py
Normal file
23
services/llm_providers/ionet_provider.py
Normal file
@@ -0,0 +1,23 @@
|
||||
import openai
|
||||
from .base_provider import BaseLLMProvider
|
||||
|
||||
class IoNetProvider(BaseLLMProvider):
|
||||
def __init__(self, api_key: str):
|
||||
super().__init__(api_key)
|
||||
self.client = openai.OpenAI(
|
||||
api_key=self.api_key,
|
||||
base_url='https://api.intelligence.io.solutions/api/v1/'
|
||||
)
|
||||
|
||||
def generate(self, model: str, system_prompt: str, user_prompt: str, temp: float):
|
||||
response = self.client.chat.completions.create(
|
||||
model=model,
|
||||
messages=[
|
||||
{'role': 'system', 'content': system_prompt},
|
||||
{'role': 'user', 'content': user_prompt},
|
||||
],
|
||||
temperature=temp,
|
||||
stream=False
|
||||
)
|
||||
text = str(response.choices[0].message.content)
|
||||
return text, text # Возвращаем как чистый текст, так и Markdown
|
||||
Reference in New Issue
Block a user