g1-demo / g1щщщ.py
enotkrutoy's picture
Rename g1.py to g1щщщ.py
51e5173 verified
import time
import json
import logging
from typing import List, Tuple, Generator, Optional, Any
import groq
# Конфигурация
DEFAULT_ITER_MODEL = "llama3-70b-8192"
DEFAULT_FINAL_MODEL = "mixtral-8x7b-32768"
MAX_TOKENS_LIMIT = 8192
RETRY_DELAY = 1.5
MAX_RETRIES = 3
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)
class APIError(Exception):
"""Базовое исключение для API ошибок"""
pass
class APIConnectionError(APIError):
"""Ошибка подключения к API"""
pass
def adjust_max_tokens(model: str, max_tokens: int) -> int:
"""Автоматическая корректировка max_tokens в зависимости от модели"""
model_limits = {
"llama3-8b-8192": 8192,
"llama3-70b-8192": 8192,
"mixtral-8x7b-32768": 32768
}
return min(max_tokens, model_limits.get(model, 4096))
def parse_json_response(raw_response: str) -> dict:
"""Улучшенный парсер с полной валидацией"""
try:
data = json.loads(raw_response)
assert isinstance(data, dict), "Ответ должен быть объектом"
assert all(k in data for k in ["title", "content", "next_action"]), "Отсутствуют обязательные ключи"
assert data["next_action"] in {"continue", "final_answer"}, "Некорректное действие"
return data
except (json.JSONDecodeError, AssertionError) as e:
logger.error(f"Ошибка парсинга: {str(e)}")
return {
"title": "Ошибка парсинга",
"content": str(e),
"next_action": "final_answer"
}
def make_api_call(
messages: List[dict],
max_tokens: int,
is_final_answer: bool = False,
custom_client: Optional[Any] = None,
iter_model: str = DEFAULT_ITER_MODEL,
final_model: str = DEFAULT_FINAL_MODEL
) -> Any:
"""Улучшенный метод вызова API"""
client = custom_client or groq.Client()
model = final_model if is_final_answer else iter_model
max_tokens = adjust_max_tokens(model, max_tokens)
params = {
"model": model,
"messages": messages,
"max_tokens": max_tokens,
"temperature": 0.5,
"response_format": {"type": "json_object"} if not is_final_answer else None
}
for attempt in range(1, MAX_RETRIES + 1):
try:
response = client.chat.completions.create(**params)
content = response.choices[0].message.content
if response.choices[0].finish_reason == "length":
logger.warning(f"Ответ обрезан! Рекомендуемый max_tokens: {max_tokens * 2}")
return content if is_final_answer else parse_json_response(content)
except groq.APIConnectionError as e:
logger.error(f"Сетевая ошибка (попытка {attempt}/{MAX_RETRIES}): {str(e)}")
if attempt == MAX_RETRIES:
raise APIConnectionError(str(e))
time.sleep(RETRY_DELAY * (2 ** attempt))
except groq.APIError as e:
logger.error(f"Ошибка API (код {e.status_code}): {e.message}")
if e.status_code >= 500:
time.sleep(RETRY_DELAY * attempt)
else:
raise APIError(e.message)
def generate_response(
prompt: str,
context: Optional[str] = None,
custom_client: Optional[Any] = None,
max_steps: int = 10,
iter_model: str = DEFAULT_ITER_MODEL,
final_model: str = DEFAULT_FINAL_MODEL
) -> Generator[Tuple[List[Tuple[str, str, float]], Optional[float]], None, None]:
"""Улучшенная генерация ответа"""
system_prompt = (
"Вы — AI-ассистент для анализа технических вопросов. "
"Формат ответа: JSON с ключами title, content, next_action. "
"Используйте русский язык и технические термины."
)
messages = [
{"role": "system", "content": system_prompt},
{"role": "user", "content": f"Контекст: {context}\n\nВопрос: {prompt}" if context else prompt}
]
steps = []
total_time = 0.0
try:
for step in range(1, max_steps + 1):
start = time.monotonic()
try:
response = make_api_call(
messages=messages,
max_tokens=MAX_TOKENS_LIMIT,
is_final_answer=False,
custom_client=custom_client,
iter_model=iter_model
)
except APIError as e:
logger.error("Критическая ошибка: %s", str(e))
yield [("Ошибка", str(e), time.monotonic() - start)], None
return
elapsed = time.monotonic() - start
total_time += elapsed
steps.append((f"Шаг {step}: {response['title']}", response["content"], elapsed))
messages.append({"role": "assistant", "content": json.dumps(response, ensure_ascii=False)})
if response["next_action"] == "final_answer":
break
yield steps, None
# Финализация
messages.append({"role": "user", "content": "Сформируйте финальный ответ с примерами кода и пояснениями."})
final_start = time.monotonic()
final_answer = make_api_call(
messages=messages,
max_tokens=MAX_TOKENS_LIMIT,
is_final_answer=True,
custom_client=custom_client,
final_model=final_model
)
total_time += time.monotonic() - final_start
steps.append(("Финальный ответ", final_answer, time.monotonic() - final_start))
except Exception as e:
logger.exception("Непредвиденная ошибка:")
steps.append(("Критическая ошибка", str(e), 0.0))
yield steps, total_time
if __name__ == "__main__":
try:
for steps, total_time in generate_response(
prompt="Опишите процесс обработки запросов в Groq API",
context="Используйте официальную документацию Groq",
iter_model="llama3-70b-8192",
final_model="mixtral-8x7b-32768"
):
if total_time is not None:
print(f"\n✅ Готово за {total_time:.2f}s")
print("=" * 60)
for title, content, t in steps:
print(f"\n🔹 {title} [{t:.2f}s]\n{content}")
except APIConnectionError as e:
print(f"🚨 Ошибка подключения: {str(e)}")
except APIError as e:
print(f"🚨 Ошибка API: {str(e)}")