add new LLM provider io.net gemini g4f
This commit is contained in:
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