File size: 5,289 Bytes
6d46033
 
f9fa035
6d46033
efb0e4f
 
 
6d46033
f9fa035
6d46033
f9fa035
 
 
 
efb0e4f
f9fa035
 
 
6d46033
f9fa035
6d46033
5656aaf
f9fa035
6d46033
f9fa035
 
 
 
32c0fc2
efb0e4f
 
f9fa035
32c0fc2
efb0e4f
f9fa035
efb0e4f
 
f9fa035
 
efb0e4f
 
 
 
 
 
 
f9fa035
 
efb0e4f
 
 
 
 
 
 
 
 
 
 
f9fa035
caa39f6
f9fa035
efb0e4f
 
 
 
f9fa035
efb0e4f
 
 
 
 
 
 
 
 
 
 
 
 
 
f9fa035
efb0e4f
f9fa035
efb0e4f
f9fa035
efb0e4f
f9fa035
efb0e4f
f9fa035
 
efb0e4f
f9fa035
 
 
efb0e4f
 
f9fa035
efb0e4f
 
f9fa035
efb0e4f
 
 
 
f9fa035
efb0e4f
 
f9fa035
efb0e4f
f9fa035
efb0e4f
f9fa035
 
 
efb0e4f
f9fa035
efb0e4f
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
import groq
import time
import os
import json
import logging

logging.basicConfig(level=logging.DEBUG)

client = groq.Groq()

def make_api_call(messages, max_tokens, is_final_answer=False, custom_client=None):
    global client
    if custom_client is not None:
        client = custom_client

    for attempt in range(3):
        try:
            if is_final_answer:
                response = 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 = client.chat.completions.create(
                    model="llama3-8b-8192",
                    messages=messages,
                    max_tokens=max_tokens,  # Используем переданный параметр max_tokens
                    temperature=0.2,
                    response_format={"type": "json_object"}
                )

                raw_response = response.choices[0].message.content
                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}")

                if all(k in parsed_response for k in ("title", "content", "next_action")):
                    return parsed_response
                else:
                    raise ValueError("JSON missing required keys")
        except Exception as e:
            if attempt == 2:
                if is_final_answer:
                    return {
                        "title": "Error",
                        "content": f"Failed to generate final answer after 3 attempts. Error: {str(e)}"
                    }
                else:
                    return {
                        "title": "Error",
                        "content": f"Failed to generate step after 3 attempts. Error: {str(e)}",
                        "next_action": "final_answer"
                    }
            time.sleep(1)

def generate_response(prompt, custom_client=None):
    """
    Генерирует ответ, возвращая промежуточные шаги рассуждений и финальный результат.
    Функция является генератором: yield возвращает кортеж (steps, total_thinking_time).
    """
    messages = [
        {"role": "system", "content": """
Вы – интеллектуальный помощник, который анализирует и объясняет свои рассуждения на русском языке шаг за шагом.
### 🔹 Формат ответа
Ваш ответ должен быть строго в JSON-формате без дополнительного текста или форматирования (например, без ```json```).
Обязательные ключи:
- "title" – краткое название шага.
- "content" – описание действий.
- "next_action" – "continue" или "final_answer".
Пример:
{"title": "Анализ задачи", "content": "Выделение ключевых элементов...", "next_action": "continue"}
🔹 Дополнительные требования:
- Используйте русский язык.
- Избегайте 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)  # Передаём max_tokens
        end_time = time.time()
        thinking_time = end_time - start_time
        total_thinking_time += thinking_time

        steps.append((f"Step {step_count}: {step_data['title']}", step_data['content'], thinking_time))
        messages.append({"role": "assistant", "content": json.dumps(step_data)})

        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