g1-demo / g123.py
enotkrutoy's picture
Rename g1.py to g123.py
f0761d4 verified
import groq
import time
import os
import json
import logging
logging.basicConfig(level=logging.DEBUG)
client = groq.Groq()
def parse_json_response(raw_response):
"""
Разбирает строку JSON и проверяет наличие обязательных ключей: title, content, next_action.
"""
logging.debug(f"RAW JSON RESPONSE: {raw_response}")
try:
parsed_response = json.loads(raw_response)
except json.JSONDecodeError as e:
raise ValueError(f"Invalid JSON: {e}, content: {raw_response}")
required_keys = {"title", "content", "next_action"}
if required_keys.issubset(parsed_response):
return parsed_response
else:
raise ValueError("JSON missing required keys")
def make_api_call(messages, max_tokens, is_final_answer=False, custom_client=None):
"""
Отправляет API-запрос с заданными сообщениями и возвращает результат.
При is_final_answer=True возвращает текст финального ответа.
В противном случае ожидается, что ответ будет в формате JSON с ключами "title", "content", "next_action".
"""
current_client = custom_client if custom_client is not None else client
for attempt in range(3):
try:
if is_final_answer:
response = current_client.chat.completions.create(
model="llama3-8b-8192",
messages=messages,
max_tokens=max_tokens,
temperature=0.2
)
# Возвращаем строку, как и ожидается для финального ответа
return response.choices[0].message.content
else:
response = current_client.chat.completions.create(
model="llama3-8b-8192",
messages=messages,
max_tokens=max_tokens,
temperature=0.2,
response_format={"type": "json_object"}
)
raw_response = response.choices[0].message.content
return parse_json_response(raw_response)
except Exception as e:
logging.exception("Attempt %d failed", attempt + 1)
if attempt == 2:
error_message = f"Failed to generate {'final answer' if is_final_answer else 'step'} after 3 attempts. Error: {str(e)}"
if is_final_answer:
return f"Error: {error_message}"
else:
return {
"title": "Error",
"content": error_message,
"next_action": "final_answer"
}
time.sleep(1)
def generate_response(prompt, custom_client=None):
"""
Генерирует цепочку рассуждений и финальный ответ по заданному запросу.
Аргументы:
prompt (str): Запрос, на который необходимо сгенерировать ответ.
custom_client (object, optional): Альтернативный клиент для API-вызовов.
Возвращает:
Генератор, yield'ящий кортеж (steps, total_thinking_time), где:
- steps: список кортежей (название шага, содержание, время обработки)
- total_thinking_time: общее время обработки (либо None до финального шага)
"""
messages = [
{"role": "system", "content": (
"Вы – интеллектуальный помощник, который анализирует и объясняет свои рассуждения на русском языке шаг за шагом.\n"
"### 🔹 Формат ответа\n"
"Ваш ответ должен быть строго в JSON-формате без дополнительного текста или форматирования (например, без ```json```).\n"
"Обязательные ключи:\n"
'- "title" – краткое название шага.\n'
'- "content" – описание действий.\n'
'- "next_action" – "continue" или "final_answer".\n'
"Пример:\n"
'{"title": "Анализ задачи", "content": "Выделение ключевых элементов...", "next_action": "continue"}\n'
"🔹 Дополнительные требования:\n"
"- Используйте русский язык.\n"
'- Избегайте Unicode-кодировок (например, писать "Привет", а не "\\u041f\\u0440\\u0438...").'
)},
{"role": "user", "content": prompt},
{"role": "assistant", "content": "Спасибо! Начинаю анализ..."}
]
steps = []
step_count = 1
total_thinking_time = 0
while True:
start_time = time.time()
step_data = make_api_call(messages, max_tokens=500, custom_client=custom_client)
end_time = time.time()
thinking_time = end_time - start_time
total_thinking_time += thinking_time
steps.append((f"Step {step_count}: {step_data.get('title', 'Без названия')}", step_data.get('content', ''), thinking_time))
messages.append({"role": "assistant", "content": json.dumps(step_data, ensure_ascii=False)})
if step_data.get('next_action') == 'final_answer' or step_count >= 25:
break
step_count += 1
yield steps, None # Возвращаем промежуточные шаги без финального времени
messages.append({
"role": "user",
"content": "Предоставьте окончательный ответ без формата JSON. Сохранить исходное форматирование из подсказки."
})
start_time = time.time()
final_data = make_api_call(messages, max_tokens=1200, is_final_answer=True, custom_client=custom_client)
end_time = time.time()
thinking_time = end_time - start_time
total_thinking_time += thinking_time
steps.append(("Final Answer", final_data, thinking_time))
yield steps, total_thinking_time