Spaces:
Runtime error
Runtime error
Update app.py
Browse files
app.py
CHANGED
|
@@ -523,10 +523,7 @@ def load_models():
|
|
| 523 |
if hybrid_search and hybrid_search.bm25:
|
| 524 |
logger.info(f"BM25 успешно инициализирован! Документов: {len(hybrid_search.corpus)}")
|
| 525 |
|
| 526 |
-
|
| 527 |
-
test_query = "метрология"
|
| 528 |
-
test_results = hybrid_search.search(test_query)
|
| 529 |
-
logger.info(f"Тестовый поиск по '{test_query}' вернул {len(test_results)} результатов")
|
| 530 |
else:
|
| 531 |
logger.error("Не удалось инициализировать BM25!")
|
| 532 |
st.error("Не удалось инициализировать текстовый поиск (BM25)")
|
|
@@ -678,15 +675,18 @@ def get_answer(question):
|
|
| 678 |
|
| 679 |
# Формируем полный ответ
|
| 680 |
answer = f"🤖 Ответ:\n\n{gpt_answer}\n\n"
|
| 681 |
-
answer += "🔍 Использованные источники:\n\n"
|
| 682 |
|
| 683 |
-
|
| 684 |
-
|
| 685 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 686 |
|
| 687 |
save_log(question, answer)
|
| 688 |
return answer
|
| 689 |
-
|
| 690 |
except Exception as e:
|
| 691 |
logger.error(f"Ошибка при генерации ответа GPT: {str(e)}")
|
| 692 |
|
|
@@ -863,137 +863,3 @@ if st.checkbox("Показать историю запросов"):
|
|
| 863 |
except Exception as e:
|
| 864 |
st.warning(f"Ошибка при загрузке логов: {e}")
|
| 865 |
|
| 866 |
-
# Диагностическая панель
|
| 867 |
-
st.sidebar.subheader("Диагностика поиска")
|
| 868 |
-
|
| 869 |
-
# Поле для тестового вопроса
|
| 870 |
-
test_question = st.sidebar.text_input("Тестовый вопрос для диагностики", "метрология")
|
| 871 |
-
|
| 872 |
-
if st.sidebar.button("Запустить диагностику FAISS"):
|
| 873 |
-
with st.sidebar.expander("Результаты диагностики", expanded=True):
|
| 874 |
-
st.write("### FAISS поиск для вопроса:")
|
| 875 |
-
st.write(f"'{test_question}'")
|
| 876 |
-
|
| 877 |
-
try:
|
| 878 |
-
# Кодируем вопрос
|
| 879 |
-
question_embedding = model.encode([test_question])
|
| 880 |
-
question_embedding = question_embedding.astype('float32')
|
| 881 |
-
|
| 882 |
-
# Ищем в FAISS индексе
|
| 883 |
-
distances, indices = faiss_index.search(question_embedding, 10)
|
| 884 |
-
|
| 885 |
-
st.write("#### Топ-10 результатов FAISS:")
|
| 886 |
-
st.write(f"Индексы: {indices[0]}")
|
| 887 |
-
st.write(f"Расстояния: {distances[0]}")
|
| 888 |
-
|
| 889 |
-
# Получаем текст чанков
|
| 890 |
-
conn = get_db_connection(VECTOR_DB_PATH)
|
| 891 |
-
cursor = conn.cursor()
|
| 892 |
-
|
| 893 |
-
st.write("#### Содержимое чанков:")
|
| 894 |
-
for i, (distance, faiss_id) in enumerate(zip(distances[0], indices[0])):
|
| 895 |
-
cursor.execute("SELECT chunk_id FROM map WHERE faiss_id = ?", (int(faiss_id),))
|
| 896 |
-
map_result = cursor.fetchone()
|
| 897 |
-
|
| 898 |
-
if map_result:
|
| 899 |
-
chunk_id = map_result['chunk_id']
|
| 900 |
-
cursor.execute("""
|
| 901 |
-
SELECT c.chunk_text, d.doc_type_short, d.doc_number, d.file_name
|
| 902 |
-
FROM content c
|
| 903 |
-
JOIN documents d ON c.document_id = d.id
|
| 904 |
-
WHERE c.id = ?
|
| 905 |
-
""", (chunk_id,))
|
| 906 |
-
chunk_result = cursor.fetchone()
|
| 907 |
-
|
| 908 |
-
if chunk_result:
|
| 909 |
-
similarity = 1 - distance
|
| 910 |
-
st.write(f"##### Чанк {i+1} (ID: {chunk_id}, Сходство: {similarity:.2f}, Расстояние: {distance:.4f})")
|
| 911 |
-
st.write(f"**Текст:** {chunk_result['chunk_text']}")
|
| 912 |
-
|
| 913 |
-
source_parts = [
|
| 914 |
-
str(chunk_result['doc_type_short']) if chunk_result['doc_type_short'] else None,
|
| 915 |
-
str(chunk_result['doc_number']) if chunk_result['doc_number'] else None,
|
| 916 |
-
str(chunk_result['file_name']) if chunk_result['file_name'] else None
|
| 917 |
-
]
|
| 918 |
-
source = " ".join(filter(None, source_parts)) or "Неизвестный источник"
|
| 919 |
-
st.write(f"**Источник:** {source}")
|
| 920 |
-
st.write("---")
|
| 921 |
-
|
| 922 |
-
conn.close()
|
| 923 |
-
except Exception as e:
|
| 924 |
-
st.error(f"Ошибка при диагностике: {e}")
|
| 925 |
-
|
| 926 |
-
if st.sidebar.button("Запустить диагностику BM25"):
|
| 927 |
-
with st.sidebar.expander("Результаты диагностики BM25", expanded=True):
|
| 928 |
-
st.write("### BM25 поиск для вопроса:")
|
| 929 |
-
st.write(f"'{test_question}'")
|
| 930 |
-
|
| 931 |
-
try:
|
| 932 |
-
# Логирование начала диагностики
|
| 933 |
-
logger.info(f"Запущена диагностика BM25 для вопроса: '{test_question}'")
|
| 934 |
-
|
| 935 |
-
# Проверка инициализации
|
| 936 |
-
if not hybrid_search:
|
| 937 |
-
error_msg = "HybridSearch не инициализирован!"
|
| 938 |
-
logger.error(error_msg)
|
| 939 |
-
st.error(error_msg)
|
| 940 |
-
st.stop()
|
| 941 |
-
|
| 942 |
-
if not hybrid_search.bm25:
|
| 943 |
-
error_msg = "BM25 не был инициализирован в HybridSearch!"
|
| 944 |
-
logger.error(error_msg)
|
| 945 |
-
st.error(error_msg)
|
| 946 |
-
st.stop()
|
| 947 |
-
|
| 948 |
-
# Выполнение поиска
|
| 949 |
-
results = hybrid_search.search(test_question, top_k=5)
|
| 950 |
-
logger.info(f"Найдено результатов BM25: {len(results)}")
|
| 951 |
-
|
| 952 |
-
if not results:
|
| 953 |
-
msg = "BM25 не вернул результатов (возможно, низкие оценки совпадения)"
|
| 954 |
-
logger.warning(msg)
|
| 955 |
-
st.warning(msg)
|
| 956 |
-
else:
|
| 957 |
-
st.success(f"Найдено результатов: {len(results)}")
|
| 958 |
-
for i, res in enumerate(results, 1):
|
| 959 |
-
logger.info(
|
| 960 |
-
f"Результат {i}: Оценка={res['score']:.2f}, "
|
| 961 |
-
f"Тип={res.get('type', 'unknown')}, "
|
| 962 |
-
f"Текст={res['text'][:50]}..."
|
| 963 |
-
)
|
| 964 |
-
|
| 965 |
-
st.markdown(f"#### Результат {i} (оценка: {res['score']:.2f})")
|
| 966 |
-
st.write(f"**Текст:** {res['text']}")
|
| 967 |
-
st.write(f"**Источник:** {res.get('source', 'нет данных')}")
|
| 968 |
-
st.write("---")
|
| 969 |
-
|
| 970 |
-
except Exception as e:
|
| 971 |
-
error_msg = f"Критическая ошибка при диагностике BM25: {str(e)}"
|
| 972 |
-
logger.exception(error_msg)
|
| 973 |
-
st.error(error_msg)
|
| 974 |
-
|
| 975 |
-
# Проверка содержимого SQLite базы
|
| 976 |
-
if st.sidebar.button("Проверить SQLite на наличие термина"):
|
| 977 |
-
try:
|
| 978 |
-
conn = get_db_connection(SQLITE_DB_PATH)
|
| 979 |
-
cursor = conn.cursor()
|
| 980 |
-
|
| 981 |
-
# Ищем все чанки, содержащие слово "метролог"
|
| 982 |
-
cursor.execute("""
|
| 983 |
-
SELECT c.id, c.chunk_text, d.doc_type_short, d.doc_number, d.file_name
|
| 984 |
-
FROM content c
|
| 985 |
-
JOIN documents d ON c.document_id = d.id
|
| 986 |
-
WHERE LOWER(c.chunk_text) LIKE LOWER(?)
|
| 987 |
-
""", (f"%{test_question}%",))
|
| 988 |
-
|
| 989 |
-
results = cursor.fetchall()
|
| 990 |
-
|
| 991 |
-
st.sidebar.write(f"Найдено {len(results)} чанков в SQLite базе:")
|
| 992 |
-
for row in results:
|
| 993 |
-
st.sidebar.write(f"Чанк ID: {row['id']}")
|
| 994 |
-
st.sidebar.write(f"Текст: {row['chunk_text'][:100]}...")
|
| 995 |
-
st.sidebar.write("---")
|
| 996 |
-
|
| 997 |
-
conn.close()
|
| 998 |
-
except Exception as e:
|
| 999 |
-
st.sidebar.error(f"Ошибка при проверке SQLite: {e}")
|
|
|
|
| 523 |
if hybrid_search and hybrid_search.bm25:
|
| 524 |
logger.info(f"BM25 успешно инициализирован! Документов: {len(hybrid_search.corpus)}")
|
| 525 |
|
| 526 |
+
|
|
|
|
|
|
|
|
|
|
| 527 |
else:
|
| 528 |
logger.error("Не удалось инициализировать BM25!")
|
| 529 |
st.error("Не удалось инициализировать текстовый поиск (BM25)")
|
|
|
|
| 675 |
|
| 676 |
# Формируем полный ответ
|
| 677 |
answer = f"🤖 Ответ:\n\n{gpt_answer}\n\n"
|
|
|
|
| 678 |
|
| 679 |
+
# Собираем уникальные источники
|
| 680 |
+
unique_sources = list(set(res['source'] for res in results))
|
| 681 |
+
|
| 682 |
+
if unique_sources:
|
| 683 |
+
answer += "📚 Использованные источники:\n"
|
| 684 |
+
for source in unique_sources:
|
| 685 |
+
answer += f"- {source}\n"
|
| 686 |
|
| 687 |
save_log(question, answer)
|
| 688 |
return answer
|
| 689 |
+
|
| 690 |
except Exception as e:
|
| 691 |
logger.error(f"Ошибка при генерации ответа GPT: {str(e)}")
|
| 692 |
|
|
|
|
| 863 |
except Exception as e:
|
| 864 |
st.warning(f"Ошибка при загрузке логов: {e}")
|
| 865 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|