diff --git a/app.py b/app.py index 0a0b395..9a87347 100644 --- a/app.py +++ b/app.py @@ -1,5 +1,4 @@ # app.py (ссылки и кнопка «Показать ещё» работают) -import json from flask import Flask, render_template, request, jsonify, session import spacy from utils.wikidata_helpers import find_and_describe @@ -11,6 +10,47 @@ nlp_ru = spacy.load("ru_core_news_sm") nlp_en = spacy.load("en_core_web_sm") +ASK_PROMPTS = { + "ru": "Пожалуйста, введите вопрос.", + "en": "Please enter a question.", + "zh": "请输入问题。", +} + +EMPTY_RESPONSES = { + "ru": "Ничего не найдено. Попробуй переформулировать.", + "en": "Nothing was found. Try rephrasing your question.", + "zh": "没有找到结果,请尝试换一种问法。", +} + +ERROR_RESPONSES = { + "timeout": { + "ru": "Wikidata долго не отвечает. Попробуй ещё раз чуть позже.", + "en": "Wikidata is taking too long to respond. Try again in a moment.", + "zh": "Wikidata 响应超时,请稍后再试。", + }, + "request": { + "ru": "Не удалось подключиться к Wikidata. Проверь соединение и повтори попытку.", + "en": "Unable to reach Wikidata right now. Please check your connection and retry.", + "zh": "目前无法连接到 Wikidata,请检查网络后重试。", + }, + "decode": { + "ru": "Wikidata прислала неожиданный ответ. Попробуй позже ещё раз.", + "en": "Wikidata returned an unexpected response. Please try again later.", + "zh": "Wikidata 返回了异常数据,请稍后再试。", + }, +} + +GENERIC_ERROR = { + "ru": "Не получилось получить данные из Wikidata. Попробуй ещё раз позже.", + "en": "Could not retrieve data from Wikidata. Please try again later.", + "zh": "未能从 Wikidata 获取数据,请稍后再试。", +} + + +def localize(table, lang, fallback): + return table.get(lang) if isinstance(table, dict) and table.get(lang) else fallback + + @app.route("/") def index(): lang = session.get("lang") or request.accept_languages.best_match(LANGUAGES.keys()) or "ru" @@ -30,22 +70,39 @@ def ask(): lang = session.get("lang", "ru") if not question: - return jsonify({"answer": "Пожалуйста, введите вопрос."}) + return jsonify({ + "answer": localize(ASK_PROMPTS, lang, ASK_PROMPTS["en"]), + "status": "empty", + "more": False, + }) nlp = nlp_ru if lang == "ru" else nlp_en doc = nlp(question) query = next((ent.text for ent in doc.ents if ent.label_ in {"PER", "ORG", "LOC"}), question) - found = find_and_describe(query, lang) + result = find_and_describe(query, lang) + + if result["error"]: + err_table = ERROR_RESPONSES.get(result["error"], GENERIC_ERROR) + return jsonify({ + "answer": localize(err_table, lang, GENERIC_ERROR["en"]), + "status": "error", + "more": False, + }) - if not found: - return jsonify({"answer": "Ничего не найдено. Попробуй переформулировать."}) + items = result["items"] or [] + if not items: + return jsonify({ + "answer": localize(EMPTY_RESPONSES, lang, EMPTY_RESPONSES["en"]), + "status": "empty", + "more": False, + }) - if len(found) == 1: - text = found[0]["text"] + if len(items) == 1: + text = items[0]["text"] more = False else: - show = found[:3] - rest = found[3:] + show = items[:3] + rest = items[3:] lines = ["Я нашёл несколько объектов:\n"] for f in show: lines.append(f"• **{f['label']}** — {f['descr']}\n[🔗 Источник]({f['url']})") @@ -54,19 +111,36 @@ def ask(): text = "\n".join(lines) more = bool(rest) - return jsonify({"answer": text, "more": more, "question": question}) + return jsonify({"answer": text, "more": more, "question": question, "status": "ok"}) @app.route("/more", methods=["POST"]) def more(): data = request.get_json() or {} question = data.get("question", "").strip() lang = session.get("lang", "ru") - found = find_and_describe(question, lang) + result = find_and_describe(question, lang) + + if result["error"]: + err_table = ERROR_RESPONSES.get(result["error"], GENERIC_ERROR) + return jsonify({ + "answer": localize(err_table, lang, GENERIC_ERROR["en"]), + "status": "error", + "more": False, + }) + + items = result["items"] or [] + if not items: + return jsonify({ + "answer": localize(EMPTY_RESPONSES, lang, EMPTY_RESPONSES["en"]), + "status": "empty", + "more": False, + }) + lines = [] - for f in found: + for f in items: lines.append(f"• **{f['label']}** — {f['descr']}\n{f['text']}") full_text = "\n\n".join(lines) - return jsonify({"answer": full_text, "more": False}) + return jsonify({"answer": full_text, "more": False, "status": "ok"}) if __name__ == "__main__": app.run(debug=True, host="127.0.0.1", port=5000) diff --git a/static/style.css b/static/style.css index 345ff0f..515a96b 100644 --- a/static/style.css +++ b/static/style.css @@ -84,6 +84,14 @@ h1 { border-top-left-radius: 4px; } +.message-error { + border-left: 3px solid #ff6b6b; +} + +.message-info { + border-left: 3px solid #4dabf7; +} + .message-time { font-size: 0.7rem; color: #777; @@ -143,6 +151,27 @@ h1 { cursor: not-allowed; } +.show-more-button { + align-self: flex-start; + margin-left: 20px; + padding: 6px 14px; + border-radius: 12px; + border: 1px solid #fbec5d; + background: transparent; + color: #fbec5d; + cursor: pointer; + transition: background 0.2s, color 0.2s; +} + +.show-more-button:hover { + background: rgba(251, 236, 93, 0.15); +} + +.show-more-button:disabled { + opacity: 0.6; + cursor: not-allowed; +} + .examples { display: flex; gap: 10px; diff --git a/templates/index.html b/templates/index.html index e123df4..1c18201 100644 --- a/templates/index.html +++ b/templates/index.html @@ -43,82 +43,135 @@