gloomy_pooplar commited on
Commit
1dbfd30
·
1 Parent(s): 0ea9cb5

feat: dialog history (10 msg) per chat_id

Browse files
Files changed (1) hide show
  1. bot.py +37 -14
bot.py CHANGED
@@ -1,8 +1,9 @@
1
- """ORTOS Telegram Bot — synchronous httpx polling.
2
  Groq (primary) -> local Llama 3.2 3B (fallback) -> 'not sure'.
3
  """
4
 
5
  import os, re, time, logging
 
6
  from openai import OpenAI
7
  import httpx
8
  from dotenv import load_dotenv
@@ -13,6 +14,8 @@ load_dotenv()
13
 
14
  logger = logging.getLogger(__name__)
15
 
 
 
16
  GROQ_API_KEY = os.getenv('GROQ_API_KEY')
17
  LLAMA_MODEL_PATH = os.getenv('LLAMA_MODEL_PATH')
18
 
@@ -58,12 +61,22 @@ def need_operator(text: str) -> bool:
58
  return False
59
 
60
 
61
- def _build_user_message(question: str, context_items):
62
  if not context_items:
63
  context = "(нет информации)"
64
  else:
65
  context = "\n\n".join(f"[{item.title}]\n{item.content}" for item in context_items)
 
 
 
 
 
 
 
 
 
66
  return (
 
67
  f"Вопрос клиента: {question}\n\n"
68
  f"Доступная информация из базы знаний ORTOS:\n{context}\n\n"
69
  "Дай точный ответ на вопрос клиента, используя ТОЛЬКО информацию выше. "
@@ -71,7 +84,7 @@ def _build_user_message(question: str, context_items):
71
  )
72
 
73
 
74
- def get_grok_response(question: str, context_items) -> str | None:
75
  if not GROQ_API_KEY:
76
  return None
77
  try:
@@ -84,7 +97,7 @@ def get_grok_response(question: str, context_items) -> str | None:
84
  model="llama-3.3-70b-versatile",
85
  messages=[
86
  {"role": "system", "content": SYSTEM_PROMPT},
87
- {"role": "user", "content": _build_user_message(question, context_items)},
88
  ],
89
  temperature=0.1,
90
  max_tokens=500,
@@ -95,14 +108,14 @@ def get_grok_response(question: str, context_items) -> str | None:
95
  return None
96
 
97
 
98
- def get_local_response(question: str, context_items) -> str | None:
99
  if _llm is None:
100
  return None
101
  try:
102
  response = _llm.create_chat_completion(
103
  messages=[
104
  {"role": "system", "content": SYSTEM_PROMPT},
105
- {"role": "user", "content": _build_user_message(question, context_items)},
106
  ],
107
  temperature=0.1,
108
  max_tokens=500,
@@ -140,22 +153,29 @@ def start_bot(bot_token: str):
140
  text_lower = text.lower()
141
  chat_id = msg["chat"]["id"]
142
 
 
 
 
143
  if text_lower in GREETINGS or any(text_lower.startswith(g) for g in GREETINGS if " " in g):
144
- msg = "Здравствуйте! Я — бот салона ортопедических стелек ORTOS. Спросите что-нибудь о наших стельках, ценах, доставке, записи на консультацию!"
145
  client.post(f"{api_url}/sendMessage", json={
146
  "chat_id": chat_id,
147
- "text": msg,
148
  })
149
- log_add(question=text, response=msg, mode="greeting", search_method="—", timing_ms=0)
 
 
150
  continue
151
 
152
  if need_operator(text):
153
- msg = "Переход на оператор"
154
  client.post(f"{api_url}/sendMessage", json={
155
  "chat_id": chat_id,
156
- "text": msg,
157
  })
158
- log_add(question=text, response=msg, mode="operator", search_method="—", timing_ms=0)
 
 
159
  continue
160
 
161
  t0 = time.time()
@@ -163,11 +183,11 @@ def start_bot(bot_token: str):
163
  results = debug["items"]
164
  t1 = time.time()
165
 
166
- response = get_grok_response(text, results)
167
  mode = "groq"
168
  llm_model = "llama-3.3-70b-versatile (Groq)"
169
  if response is None:
170
- response = get_local_response(text, results)
171
  mode = "local"
172
  llm_model = "Llama 3.2 3B (local)"
173
  if response is None:
@@ -176,6 +196,9 @@ def start_bot(bot_token: str):
176
  llm_model = ""
177
  t2 = time.time()
178
 
 
 
 
179
  client.post(f"{api_url}/sendMessage", json={
180
  "chat_id": chat_id,
181
  "text": response,
 
1
+ """ORTOS Telegram Bot — synchronous httpx polling.
2
  Groq (primary) -> local Llama 3.2 3B (fallback) -> 'not sure'.
3
  """
4
 
5
  import os, re, time, logging
6
+ from collections import deque
7
  from openai import OpenAI
8
  import httpx
9
  from dotenv import load_dotenv
 
14
 
15
  logger = logging.getLogger(__name__)
16
 
17
+ chat_history: dict[int, deque] = {}
18
+
19
  GROQ_API_KEY = os.getenv('GROQ_API_KEY')
20
  LLAMA_MODEL_PATH = os.getenv('LLAMA_MODEL_PATH')
21
 
 
61
  return False
62
 
63
 
64
+ def _build_user_message(question: str, context_items, history: deque | None = None):
65
  if not context_items:
66
  context = "(нет информации)"
67
  else:
68
  context = "\n\n".join(f"[{item.title}]\n{item.content}" for item in context_items)
69
+
70
+ hist_text = ""
71
+ if history:
72
+ lines = []
73
+ for msg in history:
74
+ role = "Клиент" if msg["role"] == "user" else "ORTOS"
75
+ lines.append(f"{role}: {msg['content']}")
76
+ hist_text = "История диалога:\n" + "\n".join(lines) + "\n\n"
77
+
78
  return (
79
+ f"{hist_text}"
80
  f"Вопрос клиента: {question}\n\n"
81
  f"Доступная информация из базы знаний ORTOS:\n{context}\n\n"
82
  "Дай точный ответ на вопрос клиента, используя ТОЛЬКО информацию выше. "
 
84
  )
85
 
86
 
87
+ def get_grok_response(question: str, context_items, history: deque | None = None) -> str | None:
88
  if not GROQ_API_KEY:
89
  return None
90
  try:
 
97
  model="llama-3.3-70b-versatile",
98
  messages=[
99
  {"role": "system", "content": SYSTEM_PROMPT},
100
+ {"role": "user", "content": _build_user_message(question, context_items, history)},
101
  ],
102
  temperature=0.1,
103
  max_tokens=500,
 
108
  return None
109
 
110
 
111
+ def get_local_response(question: str, context_items, history: deque | None = None) -> str | None:
112
  if _llm is None:
113
  return None
114
  try:
115
  response = _llm.create_chat_completion(
116
  messages=[
117
  {"role": "system", "content": SYSTEM_PROMPT},
118
+ {"role": "user", "content": _build_user_message(question, context_items, history)},
119
  ],
120
  temperature=0.1,
121
  max_tokens=500,
 
153
  text_lower = text.lower()
154
  chat_id = msg["chat"]["id"]
155
 
156
+ if chat_id not in chat_history:
157
+ chat_history[chat_id] = deque(maxlen=10)
158
+
159
  if text_lower in GREETINGS or any(text_lower.startswith(g) for g in GREETINGS if " " in g):
160
+ reply = "Здравствуйте! Я — бот салона ортопедических стелек ORTOS. Спросите что-нибудь о наших стельках, ценах, доставке, записи на консультацию!"
161
  client.post(f"{api_url}/sendMessage", json={
162
  "chat_id": chat_id,
163
+ "text": reply,
164
  })
165
+ log_add(question=text, response=reply, mode="greeting", search_method="—", timing_ms=0)
166
+ chat_history[chat_id].append({"role": "user", "content": text})
167
+ chat_history[chat_id].append({"role": "assistant", "content": reply})
168
  continue
169
 
170
  if need_operator(text):
171
+ reply = "Переход на оператор"
172
  client.post(f"{api_url}/sendMessage", json={
173
  "chat_id": chat_id,
174
+ "text": reply,
175
  })
176
+ log_add(question=text, response=reply, mode="operator", search_method="—", timing_ms=0)
177
+ chat_history[chat_id].append({"role": "user", "content": text})
178
+ chat_history[chat_id].append({"role": "assistant", "content": reply})
179
  continue
180
 
181
  t0 = time.time()
 
183
  results = debug["items"]
184
  t1 = time.time()
185
 
186
+ response = get_grok_response(text, results, chat_history[chat_id])
187
  mode = "groq"
188
  llm_model = "llama-3.3-70b-versatile (Groq)"
189
  if response is None:
190
+ response = get_local_response(text, results, chat_history[chat_id])
191
  mode = "local"
192
  llm_model = "Llama 3.2 3B (local)"
193
  if response is None:
 
196
  llm_model = ""
197
  t2 = time.time()
198
 
199
+ chat_history[chat_id].append({"role": "user", "content": text})
200
+ chat_history[chat_id].append({"role": "assistant", "content": response})
201
+
202
  client.post(f"{api_url}/sendMessage", json={
203
  "chat_id": chat_id,
204
  "text": response,