Boris commited on
Commit
2d8002a
·
1 Parent(s): 4d0311a
Files changed (2) hide show
  1. requirements.txt +96 -2
  2. src/streamlit_app.py +99 -38
requirements.txt CHANGED
@@ -1,3 +1,97 @@
1
  altair
2
- pandas
3
- streamlit
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  altair
2
+ altair==5.5.0
3
+ annotated-types==0.7.0
4
+ anyio==4.9.0
5
+ appnope==0.1.4
6
+ asttokens==3.0.0
7
+ async-timeout==4.0.3
8
+ attrs==25.3.0
9
+ blinker==1.9.0
10
+ cachetools==6.1.0
11
+ certifi==2025.6.15
12
+ charset-normalizer==3.4.2
13
+ click==8.1.8
14
+ comm==0.2.2
15
+ debugpy==1.8.14
16
+ decorator==5.2.1
17
+ dotenv==0.9.9
18
+ exceptiongroup==1.3.0
19
+ executing==2.2.0
20
+ gigachat==0.1.40
21
+ gitdb==4.0.12
22
+ GitPython==3.1.44
23
+ h11==0.16.0
24
+ httpcore==1.0.9
25
+ httpx==0.28.1
26
+ idna==3.10
27
+ importlib_metadata==8.7.0
28
+ ipykernel==6.29.5
29
+ ipython==8.18.1
30
+ jedi==0.19.2
31
+ Jinja2==3.1.6
32
+ jsonpatch==1.33
33
+ jsonpointer==3.0.0
34
+ jsonschema==4.24.0
35
+ jsonschema-specifications==2025.4.1
36
+ jupyter_client==8.6.3
37
+ jupyter_core==5.8.1
38
+ langchain==0.3.26
39
+ langchain-core==0.3.66
40
+ langchain-gigachat==0.3.11
41
+ langchain-text-splitters==0.3.8
42
+ langgraph==0.5.0
43
+ langgraph-checkpoint==2.1.0
44
+ langgraph-prebuilt==0.5.1
45
+ langgraph-sdk==0.1.72
46
+ langsmith==0.4.4
47
+ MarkupSafe==3.0.2
48
+ matplotlib-inline==0.1.7
49
+ narwhals==1.44.0
50
+ nest-asyncio==1.6.0
51
+ numpy==2.0.2
52
+ orjson==3.10.18
53
+ ormsgpack==1.10.0
54
+ packaging==24.2
55
+ pandas==2.3.0
56
+ parso==0.8.4
57
+ pexpect==4.9.0
58
+ pillow==11.2.1
59
+ platformdirs==4.3.8
60
+ prompt_toolkit==3.0.51
61
+ protobuf==6.31.1
62
+ psutil==7.0.0
63
+ ptyprocess==0.7.0
64
+ pure_eval==0.2.3
65
+ pyarrow==20.0.0
66
+ pydantic==2.11.7
67
+ pydantic_core==2.33.2
68
+ pydeck==0.9.1
69
+ Pygments==2.19.2
70
+ python-dateutil==2.9.0.post0
71
+ python-dotenv==1.1.1
72
+ pytz==2025.2
73
+ PyYAML==6.0.2
74
+ pyzmq==27.0.0
75
+ referencing==0.36.2
76
+ requests==2.32.4
77
+ requests-toolbelt==1.0.0
78
+ rpds-py==0.25.1
79
+ six==1.17.0
80
+ smmap==5.0.2
81
+ sniffio==1.3.1
82
+ SQLAlchemy==2.0.41
83
+ stack-data==0.6.3
84
+ streamlit==1.46.1
85
+ tenacity==9.1.2
86
+ toml==0.10.2
87
+ tornado==6.5.1
88
+ traitlets==5.14.3
89
+ types-requests==2.32.4.20250611
90
+ typing-inspection==0.4.1
91
+ typing_extensions==4.14.0
92
+ tzdata==2025.2
93
+ urllib3==2.5.0
94
+ wcwidth==0.2.13
95
+ xxhash==3.5.0
96
+ zipp==3.23.0
97
+ zstandard==0.23.0
src/streamlit_app.py CHANGED
@@ -1,40 +1,101 @@
1
- import altair as alt
2
- import numpy as np
3
- import pandas as pd
4
  import streamlit as st
 
 
 
5
 
6
- """
7
- # Welcome to Streamlit!
8
-
9
- Edit `/streamlit_app.py` to customize this app to your heart's desire :heart:.
10
- If you have any questions, checkout our [documentation](https://docs.streamlit.io) and [community
11
- forums](https://discuss.streamlit.io).
12
-
13
- In the meantime, below is an example of what you can do with just a few lines of code:
14
- """
15
-
16
- num_points = st.slider("Number of points in spiral", 1, 10000, 1100)
17
- num_turns = st.slider("Number of turns in spiral", 1, 300, 31)
18
-
19
- indices = np.linspace(0, 1, num_points)
20
- theta = 2 * np.pi * num_turns * indices
21
- radius = indices
22
-
23
- x = radius * np.cos(theta)
24
- y = radius * np.sin(theta)
25
-
26
- df = pd.DataFrame({
27
- "x": x,
28
- "y": y,
29
- "idx": indices,
30
- "rand": np.random.randn(num_points),
31
- })
32
-
33
- st.altair_chart(alt.Chart(df, height=700, width=700)
34
- .mark_point(filled=True)
35
- .encode(
36
- x=alt.X("x", axis=None),
37
- y=alt.Y("y", axis=None),
38
- color=alt.Color("idx", legend=None, scale=alt.Scale()),
39
- size=alt.Size("rand", legend=None, scale=alt.Scale(range=[1, 150])),
40
- ))
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  import streamlit as st
2
+ from langchain_core.messages import HumanMessage, AIMessage
3
+ from services.get_classification import get_graph_class
4
+ from datetime import datetime
5
 
6
+
7
+ def message_to_dict(messages):
8
+ result = []
9
+ for message in messages:
10
+ if isinstance(message, HumanMessage) or isinstance(message, AIMessage):
11
+ print("message:", message.content)
12
+ if message.content == "" or message.content is None:
13
+ continue
14
+ if isinstance(message, HumanMessage):
15
+ result.append({"role": "user", "content": message.content})
16
+ elif isinstance(message, AIMessage):
17
+ result.append({"role": "assistant", "content": message.content})
18
+ print("-" * 100)
19
+ return result
20
+
21
+
22
+ def find_last_bot_message(messages):
23
+ """Находит последнее сообщение бота"""
24
+ for message in messages[::-1]:
25
+ if isinstance(message, AIMessage) and len(message.content) > 0:
26
+ return message.content
27
+ return None
28
+
29
+
30
+ def display_chat_messages():
31
+ """Отображает историю сообщений в чате"""
32
+ for message in st.session_state.messages:
33
+ with st.chat_message(message["role"]):
34
+ st.markdown(message["content"])
35
+
36
+
37
+ def save_broken_case():
38
+ messages_dict = st.session_state.messages
39
+ result_str = ""
40
+ for elem in messages_dict:
41
+ role = elem["role"]
42
+ content = elem["content"]
43
+ result_str += f"{role}: {content}\n"
44
+
45
+ current_datetime = datetime.now()
46
+ formatted_datetime = current_datetime.strftime("%Y-%m-%d %H:%M:%S")
47
+
48
+ with open("/Users/admin/my_documents/retrieval_part/services/broken_cases.txt", "a") as file:
49
+ file.write(f"{formatted_datetime}\n" + result_str + "\n" + "-" * 50 + "\n\n")
50
+
51
+
52
+ def handle_user_input():
53
+ """Обрабатывает ввод пользователя и генерирует ответ бота"""
54
+ if prompt := st.chat_input("Введите ваш вопрос"):
55
+ st.session_state.messages.append({"role": "user", "content": prompt})
56
+ if prompt.lower().startswith("log"):
57
+ save_broken_case()
58
+ st.session_state.messages = []
59
+ display_chat_messages()
60
+ else:
61
+ with st.chat_message("user"):
62
+ st.markdown(prompt)
63
+
64
+ if "bot" not in st.session_state:
65
+ st.session_state.bot = get_graph_class(prompt)
66
+ st.session_state.bot.invoke(prompt)
67
+
68
+ # Извлекаем последнее сообщение бота
69
+ last_bot_message = find_last_bot_message(st.session_state.bot.messages)
70
+ st.session_state.messages.append(
71
+ {"role": "assistant", "content": last_bot_message}
72
+ )
73
+ with st.chat_message("assistant"):
74
+ st.markdown(last_bot_message)
75
+
76
+
77
+ def clear_chat():
78
+ """Очищает чат и пересоздает бота"""
79
+ st.session_state.messages = []
80
+ del st.session_state.bot
81
+
82
+
83
+ def main():
84
+ """Основная функция приложения"""
85
+ # Заголовок приложения
86
+ st.title("Чат-бот технической поддержки OpenVPN")
87
+
88
+ # Кнопка очистки чата
89
+ if st.button("Clear"):
90
+ clear_chat()
91
+
92
+ if "messages" not in st.session_state:
93
+ st.session_state.messages = []
94
+
95
+ # Отображение чата и обработка ввода
96
+ display_chat_messages()
97
+ handle_user_input()
98
+
99
+
100
+ if __name__ == "__main__":
101
+ main()