File size: 6,477 Bytes
e1600e7
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
import os
import streamlit as st
from langchain_groq import ChatGroq
from langchain_huggingface import HuggingFaceEmbeddings
from langchain_community.vectorstores import FAISS
from langchain_text_splitters import RecursiveCharacterTextSplitter
from langchain_community.document_loaders import WebBaseLoader
from langchain_core.prompts import PromptTemplate
from langchain_core.output_parsers import StrOutputParser
from langchain_core.runnables import RunnablePassthrough, RunnableLambda
from requests.exceptions import RequestException, Timeout

# Загрузка переменных окружения
if os.path.exists(".env"):
    load_dotenv(verbose=True)

# Загрузка API-ключей
try:
    GROQ_API_KEY = st.secrets["GROQ_API_KEY"]
    USER_AGENT = st.secrets["USER_AGENT"]
    LANGSMITH_TRACING = st.secrets["LANGSMITH_TRACING"] 
    LANGSMITH_ENDPOINT = st.secrets["LANGSMITH_ENDPOINT"]
    LANGSMITH_API_KEY = st.secrets["LANGSMITH_API_KEY"]
    LANGSMITH_PROJECT = st.secrets["LANGSMITH_PROJECT"]
    OPENAI_API_KEY = st.secrets["OPENAI_API_KEY"]
except FileNotFoundError:
    GROQ_API_KEY = os.getenv("GROQ_API_KEY")
    USER_AGENT = os.getenv("USER_AGENT")
    LANGSMITH_TRACING = os.getenv("LANGSMITH_TRACING") 
    LANGSMITH_ENDPOINT = os.getenv("LANGSMITH_ENDPOINT")
    LANGSMITH_API_KEY = os.getenv("LANGSMITH_API_KEY")
    LANGSMITH_PROJECT = os.getenv("LANGSMITH_PROJECT")
    OPENAI_API_KEY = os.getenv("OPENAI_API_KEY")

# Проверка API-ключей
if not all([GROQ_API_KEY, USER_AGENT, LANGSMITH_TRACING, LANGSMITH_ENDPOINT, LANGSMITH_API_KEY, LANGSMITH_PROJECT, OPENAI_API_KEY]):
    st.error("Ошибка: Не все переменные окружения заданы.")
    st.stop()

# Инициализация LLM
try:
    llm = ChatGroq(model_name="llama-3.3-70b-versatile", temperature=0.6, api_key=GROQ_API_KEY)
    print("[DEBUG] LLM успешно инициализирован")
except Exception as e:
    st.error(f"Ошибка инициализации LLM: {e}")
    st.stop()

# Инициализация эмбеддингов
embeddings_model = HuggingFaceEmbeddings(model_name="intfloat/multilingual-e5-large-instruct")
print("[DEBUG] Модель эмбеддингов загружена")

# Список страниц для анализа
urls = [
    "https://status.law",  
    "https://status.law/about",
    "https://status.law/careers",
    "https://status.law/challenging-sanctions",
    "https://status.law/contact", 
    "https://status.law/cross-border-banking-legal-issues", 
    "https://status.law/extradition-defense", 
    "https://status.law/international-prosecution-protection", 
    "https://status.law/interpol-red-notice-removal",  
    "https://status.law/practice-areas",  
    "https://status.law/reputation-protection",
    "https://status.law/faq"
]

# Путь к файлу векторного хранилища
VECTOR_STORE_PATH = "vector_store"

# Функция для создания базы знаний
def build_knowledge_base():
    documents = []
    for url in urls:
        try:
            loader = WebBaseLoader(url)
            documents.extend(loader.load(timeout=10))
            st.write(f"[DEBUG] Загружен контент с {url}")
        except (RequestException, Timeout) as e:
            st.write(f"[ERROR] Ошибка загрузки страницы {url}: {e}")
    text_splitter = RecursiveCharacterTextSplitter(chunk_size=500, chunk_overlap=100)
    chunks = text_splitter.split_documents(documents)
    st.write(f"[DEBUG] Разбито на {len(chunks)} фрагментов")
    vector_store = FAISS.from_documents(chunks, embeddings_model)
    vector_store.save_local(VECTOR_STORE_PATH)
    st.write("[DEBUG] Векторное хранилище создано и сохранено")
    return vector_store

# Функция для загрузки базы знаний
@st.cache_resource
def load_knowledge_base():
    if os.path.exists(VECTOR_STORE_PATH):
        st.write("[DEBUG] Загрузка существующего векторного хранилища")
        return FAISS.load_local(VECTOR_STORE_PATH, embeddings_model)
    else:
        st.write("[DEBUG] Векторное хранилище не найдено, создание нового")
        return build_knowledge_base()

# Загрузка или создание базы знаний
vector_store = load_knowledge_base()

# Промпт для бота
template = """
You are a helpful legal assistant that answers questions based on information from status.law.
Answer accurately and concisely.
Question: {question}
Only use the provided context to answer the question.
Context: {context}
"""
prompt = PromptTemplate.from_template(template)

# Инициализация цепочки обработки запроса
if "chain" not in st.session_state:
    st.session_state.chain = (
        RunnableLambda(lambda x: {"context": x["context"], "question": x["question"]}) 
        | prompt
        | llm
        | StrOutputParser()
    )
chain = st.session_state.chain

# Интерфейс Streamlit
st.set_page_config(page_title="Legal Chatbot", page_icon="🤖")
st.title("🤖 Legal Chatbot")
st.write("Этот бот отвечает на юридические вопросы, используя информацию с сайта status.law.")

# Поле для ввода вопроса
user_input = st.text_input("Введите ваш вопрос:")
if st.button("Отправить") and user_input:
    # Поиск релевантных документов
    retrieved_docs = vector_store.similarity_search(user_input)
    context_text = "\n\n".join([doc.page_content for doc in retrieved_docs])

    # Генерация ответа
    response = chain.invoke({"question": user_input, "context": context_text})
    
    # Сохранение истории сообщений
    if "message_history" not in st.session_state:
        st.session_state.message_history = []
    st.session_state.message_history.append({"question": user_input, "answer": response})
    
    # Вывод ответа
    st.write(response)

# Вывод истории сообщений
if "message_history" in st.session_state:
    st.write("### История сообщений")
    for msg in st.session_state.message_history:
        st.write(f"**User:** {msg['question']}")
        st.write(f"**Bot:** {msg['answer']}")