KennyOry commited on
Commit
c21e488
·
verified ·
1 Parent(s): d8671b8

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +97 -86
app.py CHANGED
@@ -57,109 +57,120 @@ logging.basicConfig(
57
  ]
58
  )
59
 
60
-
61
  def generate_search_query(prompt: str) -> dict:
62
- BRAND_ALIASES = {
63
- "hewlett-packard": "HP", "hewlett packard": "HP", "hp": "HP", "хп": "HP", "эйчпи": "HP",
64
- "коника": "Konica Minolta", "конике": "Konica Minolta", "коника минолта": "Konica Minolta",
65
- "кэнон": "Canon", "кэноне": "Canon", "канон": "Canon", "каноне": "Canon",
66
- "кенон": "Canon", "кеноне": "Canon", "canon": "Canon",
67
- "ксерокс": "Xerox", "ксероксе": "Xerox", "херокс": "Xerox", "хероксе": "Xerox", "херох": "Xerox",
68
- "epson": "Epson", "эпсон": "Epson", "brother": "Brother", "братер": "Brother", "братэр": "Brother",
69
- "kyocera": "Kyocera", "киосера": "Kyocera", "ricoh": "Ricoh", "рико": "Ricoh", "lexmark": "Lexmark",
70
- "лексмарк": "Lexmark", "oki": "OKI", "оки": "OKI", "sharp": "Sharp", "шарп": "Sharp",
71
- "samsung": "Samsung", "самсунг": "Samsung", "dell": "Dell", "делл": "Dell"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
72
  }
73
-
74
- # Улучшенное регулярное выражение для кодов ошибок
75
- error_pattern = r'\b(?:[A-Za-z]{1,4}[- _]?)?\d{2,5}[A-Za-z]?\b|\bC[- ]?\d{4,5}\b|\bE[- ]?[A-Z]\d{2,3}\b'
76
 
77
- messages = [
78
- {
79
- "role": "system",
80
- "content": """Извлеки информацию из запроса в формате JSON:
81
- - brand: английское название бренда (HP, Canon, Konica Minolta и т.д.)
82
- - model: модель оборудования
83
- - error_code: код ошибки (если есть)
84
- - problem_description: краткое описание проблемы на русском
85
-
86
- Примеры:
87
- Запрос: "HP LaserJet 1020 не включается"
88
- Ответ: {"brand": "HP", "model": "LaserJet 1020", "error_code": "", "problem_description": "Принтер не включается"}
89
-
90
- Запрос: "Canon imagePROGRAF TM-300 ошибка E07"
91
- Ответ: {"brand": "Canon", "model": "imagePROGRAF TM-300", "error_code": "E07", "problem_description": "Ошибка E07"}
92
- """
93
- },
94
- {"role": "user", "content": prompt}
95
- ]
96
-
 
 
 
 
 
 
 
 
97
  try:
 
98
  response = mistral_client.chat.complete(
99
  model=MISTRAL_MODEL,
100
- messages=messages,
 
 
 
101
  temperature=0.1,
102
- max_tokens=250,
103
  response_format={"type": "json_object"}
104
  )
105
 
 
106
  json_data = json.loads(response.choices[0].message.content)
107
 
108
- # Улучшенное извлечение кода ошибки, если Mistral его пропустил
109
- if not json_data.get('error_code', ''):
110
- error_match = re.search(error_pattern, prompt, re.IGNORECASE)
111
- if error_match:
112
- json_data['error_code'] = error_match.group(0).strip()
113
-
114
- # Улучшенное извлечение модели, если Mistral ее пропустил
115
- if not json_data.get('model', ''):
116
- # Ищем последовательность из 2-5 слов, начинающуюся с заглавной буквы или цифр
117
- model_match = re.search(r'(\b[A-Z0-9][\w-]+(?:\s+[A-Z0-9][\w-]+){1,4}\b', prompt)
118
- if model_match:
119
- json_data['model'] = model_match.group(0).strip()
120
-
121
- # Формируем поисковый запрос
122
- if json_data.get('error_code', ''):
123
- search_query = f"{json_data['brand']} {json_data['model']} ошибка {json_data['error_code']}"
124
- else:
125
- search_query = f"{json_data['brand']} {json_data['model']} {json_data['problem_description']}"
126
-
127
- json_data['search_query'] = re.sub(r'\s+', ' ', search_query).strip()
 
 
 
 
 
128
  return json_data
129
 
130
  except Exception as e:
131
- message_queue.put(('log', f"❌ Ошибка извлечения данных: {str(e)}"))
132
-
133
- # Расширенный fallback для брендов
134
- brand = ""
135
- prompt_lower = prompt.lower()
136
- for name, alias in BRAND_ALIASES.items():
137
- if name in prompt_lower:
138
- brand = alias
139
- break
140
-
141
- # Извлечение кода ошибки
142
- error_match = re.search(error_pattern, prompt, re.IGNORECASE)
143
- error_code = error_match.group(0).strip() if error_match else ""
144
 
145
- # Извлечение модели (более простое)
146
- model_parts = []
147
- for word in prompt.split():
148
- if word[0].isupper() or word.isupper() or word.isdigit():
149
- model_parts.append(word)
150
- elif model_parts:
151
- break
152
- model = " ".join(model_parts) if model_parts else ""
153
-
154
  return {
155
- 'brand': brand,
156
- 'model': model,
157
- 'error_code': error_code,
158
- 'problem_description': prompt,
159
- 'search_query': prompt
160
  }
161
 
162
-
163
  def web_search(query: str) -> tuple:
164
  try:
165
  message_queue.put(('log', f"🔍 Провожу поиск по запросу: {query}"))
@@ -169,8 +180,8 @@ def web_search(query: str) -> tuple:
169
  "api_key": os.getenv("SERPAPI_KEY"),
170
  "engine": "google",
171
  "q": query,
172
- "hl": "ru",
173
- "gl": "ru",
174
  "num": 10,
175
  "safe": "off",
176
  }
 
57
  ]
58
  )
59
 
 
60
  def generate_search_query(prompt: str) -> dict:
61
+ # Создаем расширенный системный промт с требованием англоязычного вывода
62
+ system_prompt = """
63
+ You are a technical expert. Extract structured data from the user's query and generate an English search query.
64
+ Return data in strict JSON format with these fields:
65
+ - brand: English brand name (HP, Canon, Konica Minolta, etc.)
66
+ - model: equipment model (model name only)
67
+ - error_code: error code (if present)
68
+ - problem_description: brief English problem description (1-2 sentences)
69
+ - search_query: full English search query for technical documentation
70
+
71
+ Important rules:
72
+ 1. All fields MUST be in English
73
+ 2. For brands use official English names
74
+ 3. Remove brand mentions and the word "error" from model name
75
+ 4. If error code is specified - include it in search_query
76
+ 5. Problem description should be concise technical terms (max 7 words)
77
+ 6. Search query should be optimized for technical documentation search
78
+
79
+ Examples:
80
+
81
+ Query: "Коника Минольта bizhub 368 выдает ошибку C-2557"
82
+ Response: {
83
+ "brand": "Konica Minolta",
84
+ "model": "bizhub 368",
85
+ "error_code": "C-2557",
86
+ "problem_description": "C-2557 error code",
87
+ "search_query": "Konica Minolta bizhub 368 C-2557 error code technical solution"
88
  }
 
 
 
89
 
90
+ Query: "Не печатает HP LaserJet Pro M404dn"
91
+ Response: {
92
+ "brand": "HP",
93
+ "model": "LaserJet Pro M404dn",
94
+ "error_code": "",
95
+ "problem_description": "printer not printing",
96
+ "search_query": "HP LaserJet Pro M404dn not printing technical fix"
97
+ }
98
+
99
+ Query: "Hewlett-Packard Color LaserJet MFP E77825 Ошибка 63.00.41"
100
+ Response: {
101
+ "brand": "HP",
102
+ "model": "Color LaserJet MFP E77825",
103
+ "error_code": "63.00.41",
104
+ "problem_description": "error 63.00.41",
105
+ "search_query": "HP Color LaserJet MFP E77825 error 63.00.41 technical solution"
106
+ }
107
+
108
+ Query: "Canon imagePROGRAF TM-200 Ошибка EC12-2F2B"
109
+ Response: {
110
+ "brand": "Canon",
111
+ "model": "imagePROGRAF TM-200",
112
+ "error_code": "EC12-2F2B",
113
+ "problem_description": "EC12-2F2B error",
114
+ "search_query": "Canon imagePROGRAF TM-200 EC12-2F2B error troubleshooting"
115
+ }
116
+ """
117
+
118
  try:
119
+ # Запрашиваем структурированные данные у Mistral
120
  response = mistral_client.chat.complete(
121
  model=MISTRAL_MODEL,
122
+ messages=[
123
+ {"role": "system", "content": system_prompt},
124
+ {"role": "user", "content": prompt}
125
+ ],
126
  temperature=0.1,
127
+ max_tokens=350,
128
  response_format={"type": "json_object"}
129
  )
130
 
131
+ # Парсим JSON ответ
132
  json_data = json.loads(response.choices[0].message.content)
133
 
134
+ # Простая валидация и нормализация полей
135
+ required_fields = ['brand', 'model', 'error_code', 'problem_description', 'search_query']
136
+ for field in required_fields:
137
+ if field not in json_data:
138
+ json_data[field] = ""
139
+
140
+ # Очистка модели от бренда
141
+ if json_data['brand'] and json_data['model']:
142
+ json_data['model'] = re.sub(
143
+ re.escape(json_data['brand']),
144
+ '',
145
+ json_data['model'],
146
+ flags=re.IGNORECASE
147
+ ).strip()
148
+
149
+ # Обеспечиваем англоязычный поисковый запрос
150
+ if not json_data['search_query']:
151
+ # Fallback генерация поискового запроса
152
+ search_parts = [json_data['brand'], json_data['model']]
153
+ if json_data['error_code']:
154
+ search_parts.append(f"error {json_data['error_code']}")
155
+ if json_data['problem_description']:
156
+ search_parts.append(json_data['problem_description'])
157
+ json_data['search_query'] = " ".join(search_parts).strip() + " technical solution"
158
+
159
  return json_data
160
 
161
  except Exception as e:
162
+ # Простой fallback на случай ошибки
163
+ error_msg = f"❌ Ошибка извлечения данных: {str(e)}"
164
+ message_queue.put(('log', error_msg))
 
 
 
 
 
 
 
 
 
 
165
 
 
 
 
 
 
 
 
 
 
166
  return {
167
+ 'brand': "",
168
+ 'model': "",
169
+ 'error_code': "",
170
+ 'problem_description': "",
171
+ 'search_query': prompt # Используем оригинальный запрос как fallback
172
  }
173
 
 
174
  def web_search(query: str) -> tuple:
175
  try:
176
  message_queue.put(('log', f"🔍 Провожу поиск по запросу: {query}"))
 
180
  "api_key": os.getenv("SERPAPI_KEY"),
181
  "engine": "google",
182
  "q": query,
183
+ "hl": "en",
184
+ "gl": "us",
185
  "num": 10,
186
  "safe": "off",
187
  }