Alessio-Chiovelli commited on
Commit
cfd8b92
·
verified ·
1 Parent(s): 766f341

Upload 20 files

Browse files

Prova Commit Frontend

.gitattributes CHANGED
@@ -33,3 +33,5 @@ saved_model/**/* filter=lfs diff=lfs merge=lfs -text
33
  *.zip filter=lfs diff=lfs merge=lfs -text
34
  *.zst filter=lfs diff=lfs merge=lfs -text
35
  *tfevents* filter=lfs diff=lfs merge=lfs -text
 
 
 
33
  *.zip filter=lfs diff=lfs merge=lfs -text
34
  *.zst filter=lfs diff=lfs merge=lfs -text
35
  *tfevents* filter=lfs diff=lfs merge=lfs -text
36
+ static/2.png filter=lfs diff=lfs merge=lfs -text
37
+ static/3.png filter=lfs diff=lfs merge=lfs -text
app.py ADDED
@@ -0,0 +1,16 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from frontend_pages import st
2
+ from frontend_pages.ConfigPage import ConfigPage
3
+ from frontend_pages.ChatModelPage import ChatModelPage
4
+ from frontend_pages.Dashboard import Dashboard
5
+
6
+ st.set_page_config(layout="wide")
7
+
8
+ PAGES = {
9
+ "Configurazione": ConfigPage,
10
+ "Dashboard": ChatModelPage,
11
+ # "Dashboard": Dashboard,
12
+ }
13
+
14
+ if __name__ == "__main__":
15
+ PAGES[st.sidebar.selectbox("Select a page", list(PAGES.keys()))]().render()
16
+ # PAGES["Chat with AI Model"]().render()
frontend_pages/BasePage.py ADDED
@@ -0,0 +1,22 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from . import st, ABC, abstractmethod
2
+
3
+ class BasePage(ABC):
4
+ _instance = None
5
+
6
+ def __new__(cls, *args, **kwargs):
7
+ if cls._instance is None:
8
+ cls._instance = super(BasePage, cls).__new__(cls)
9
+ return cls._instance
10
+
11
+ def __init__(self):
12
+ if not hasattr(self, 'initialized'):
13
+ self.api_keys = []
14
+ self.initialized = True
15
+
16
+ @abstractmethod
17
+ def render(self, keys : dict[str, str | None], **kwargs):
18
+ with st.sidebar:
19
+ st.title("API Key Input")
20
+ for key, default_value in keys.items():
21
+ st.session_state[key] = st.text_input(f"Enter API key for {key}", value=default_value, type="password")
22
+ st.divider()
frontend_pages/ChatModelPage.py ADDED
@@ -0,0 +1,148 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from . import os, st, re, requests, stylable_container
2
+ from .BasePage import BasePage
3
+
4
+ from .modals import get_base64_image, create_call_modal, upload_call_modal_and_actions
5
+
6
+ class RouterAgent:
7
+ def __call__(self, **kwargs):
8
+ agent_prompt_slash_code = re.findall(r"(\/[\w\-_]*)? *(.*)", kwargs.get('prompt'))
9
+ uri = agent_prompt_slash_code[0][0] or "/explain"
10
+ prompt = agent_prompt_slash_code[0][1]
11
+ print(f'{uri = }', f'{prompt = }')
12
+ response = requests.post(os.getenv("BACKEND_URL", "http://127.0.0.1:5000") + f'{uri}', json = {"prompt" : prompt})
13
+ if response.status_code != 200:
14
+ st.error(f"Error: {response.text}")
15
+ return
16
+ response_json = response.json()
17
+ print(f'{response_json = }')
18
+ return response_json["message"]
19
+
20
+ class ChatModelPage(BasePage):
21
+ def __init__(self):
22
+ super().__init__()
23
+ self.model = None
24
+ self.router_agent = RouterAgent()
25
+
26
+ def render(self):
27
+ st.title("Dashboard")
28
+ self.sidebar_elements()
29
+ self.upfront_page()
30
+ self.init_messages()
31
+ self.reset_messages_sidebar_button()
32
+ # Display chat messages from history on app rerun
33
+ for message in st.session_state.messages:
34
+ with st.chat_message(message["role"]):
35
+ st.markdown(message["content"])
36
+ # React to user input
37
+ if prompt := st.chat_input("What is up?"):
38
+ # Display user message in chat message container
39
+ st.chat_message("user").markdown(prompt)
40
+ # Add user message to chat history
41
+ st.session_state.messages.append({"role": "user", "content": prompt})
42
+ response = self.get_agent_response(prompt = prompt)
43
+ # Display assistant response in chat message container
44
+ with st.chat_message("assistant"):st.markdown(response)
45
+ # Add assistant response to chat history
46
+ st.session_state.messages.append({"role": "assistant", "content": response})
47
+
48
+ def init_messages(self):
49
+ # Initialize chat history
50
+ if "messages" not in st.session_state:
51
+ st.session_state.messages = []
52
+
53
+ def get_agent_response(self, **kwargs):
54
+ # Get agent response
55
+ return self.router_agent(**kwargs)
56
+
57
+ def reset_messages_sidebar_button(self):
58
+ with st.sidebar:
59
+ # Reset chat history
60
+ if st.button("Reset chat"):
61
+ st.session_state.messages = []
62
+
63
+ def upfront_page(self):
64
+ tabs_and_dialogs_cols = st.columns(2)
65
+ with tabs_and_dialogs_cols[0]:
66
+ with stylable_container(
67
+ key = "create-call-button",
68
+ css_styles = f"""
69
+ button {{
70
+ background-image: url("data:image/png;base64,{get_base64_image("static/NewCallButton.png")}");
71
+ background-size: cover;
72
+ background-repeat: no-repeat;
73
+ background-position: center;
74
+ background-color: transparent;
75
+ border: none;
76
+ width: 298px;
77
+ height: 164px;
78
+ }}"""
79
+ ):
80
+ clicked_create_call_button = st.button("", key = "create-call-button")
81
+ if clicked_create_call_button:create_call_modal()
82
+ with stylable_container(
83
+ key = "upload-call-button",
84
+ css_styles = f"""
85
+ button {{
86
+ background-image: url("data:image/png;base64,{get_base64_image("static/UploadCallButton.png")}");
87
+ background-size: cover;
88
+ background-repeat: no-repeat;
89
+ background-position: center;
90
+ background-color: transparent;
91
+ border: none;
92
+ width: 298px;
93
+ height: 164px;
94
+ }}"""
95
+ ):
96
+ clicked_create_call_button = st.button('', key='upload-call-button')
97
+ if clicked_create_call_button:upload_call_modal_and_actions()
98
+ with tabs_and_dialogs_cols[1]:
99
+ tabs = st.tabs(["Tasks"])
100
+ func_of_tabs = [ self.tasks ]
101
+ for tab, func in zip(tabs, func_of_tabs):
102
+ with tab:func()
103
+
104
+ def sidebar_elements(self):
105
+ actions = {"Project" : self.projects, "Team" : self.team }
106
+ with st.sidebar:
107
+ for label, action in actions.items():
108
+ st.header(label)
109
+ action()
110
+ st.divider()
111
+
112
+ def team(self):
113
+ teams_per_project = {"Projects": "Team1", "Projects2": "Team2", "Projects3": "Team3"}
114
+ st.write(teams_per_project[st.session_state.selected_project])
115
+ # st.image("static/2.png")
116
+
117
+ def tasks(self):
118
+ st.image("static/3.png")
119
+
120
+ def projects(self):
121
+ projects_available = ["Projects", "Projects2", "Projects3"]
122
+ st.session_state.selected_project = st.selectbox("Projects available", projects_available)
123
+
124
+ # def choose_agent(self):
125
+ # # Choose agent
126
+ # class RouterAgent:
127
+ # def __call__(self, **kwargs):
128
+ # agent_prompt_slash_code = re.findall(r"(\/[\w\-_]*) *(.*)", kwargs.get('prompt'))
129
+ # uri = agent_prompt_slash_code[0][0]
130
+ # prompt = agent_prompt_slash_code[0][1]
131
+ # response = requests.post(os.getenv("BACKEND_URL") + f'/{uri}', json = {"prompt" : prompt})
132
+ # if response.status_code != 200:
133
+ # st.error(f"Error: {response.text}")
134
+ # return
135
+ # return response.json()
136
+ # # agents = {
137
+ # # "Dummy Agent": {
138
+ # # "_class" : RouterAgent,
139
+ # # },
140
+ # # "Meeting Scheduler Agent": {
141
+ # # "_class" : DummyAgent,
142
+ # # }
143
+ # # }
144
+ # # agent_selected = st.sidebar.selectbox("Select agent", list(agents.keys()))
145
+ # # agent_init_js = agents[agent_selected]
146
+ # RouterAgent()
147
+ # agent_class = agent_init_js.pop("_class")
148
+ # return agent_class(**agent_init_js)
frontend_pages/ConfigPage.py ADDED
@@ -0,0 +1,6 @@
 
 
 
 
 
 
 
1
+ from . import os
2
+ from .BasePage import BasePage
3
+
4
+ class ConfigPage(BasePage):
5
+ def render(self):
6
+ super().render(keys={"WATSON_API_KEY": os.getenv("WATSON_API_KEY")})
frontend_pages/Dashboard.py ADDED
@@ -0,0 +1,72 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from . import os, st, stylable_container
2
+ from .BasePage import BasePage
3
+
4
+ from .modals import get_base64_image, create_call_modal, upload_call_modal_and_actions
5
+
6
+ class Dashboard(BasePage):
7
+ def render(self):
8
+ st.title("Dashboard")
9
+ self.sidebar_elements()
10
+ self.upfront_page()
11
+
12
+ def upfront_page(self):
13
+ with st.sidebar:
14
+ tabs_and_dialogs_cols = st.columns(2)
15
+ with tabs_and_dialogs_cols[0]:
16
+ with stylable_container(
17
+ key = "create-call-button",
18
+ # css_styles = f"""
19
+ # button {{
20
+ # background-image: url("data:image/png;base64,{get_base64_image("static/NewCallButton.png")}");
21
+ # background-size: cover;
22
+ # background-repeat: no-repeat;
23
+ # background-position: center;
24
+ # background-color: transparent;
25
+ # border: none;
26
+ # width: 298px;
27
+ # height: 164px;
28
+ # }}"""
29
+ ):
30
+ clicked_create_call_button = st.button("create-call-button", key = "create-call-button")
31
+ if clicked_create_call_button:create_call_modal()
32
+ with stylable_container(
33
+ key = "upload-call-button",
34
+ # css_styles = f"""
35
+ # button {{
36
+ # background-image: url("data:image/png;base64,{get_base64_image("static/UploadCallButton.png")}");
37
+ # background-size: cover;
38
+ # background-repeat: no-repeat;
39
+ # background-position: center;
40
+ # background-color: transparent;
41
+ # border: none;
42
+ # width: 298px;
43
+ # height: 164px;
44
+ # }}"""
45
+ ):
46
+ clicked_create_call_button = st.button('upload-call-button', key='upload-call-button')
47
+ if clicked_create_call_button:upload_call_modal_and_actions()
48
+ with tabs_and_dialogs_cols[1]:
49
+ tabs = st.tabs(["Tasks"])
50
+ func_of_tabs = [ self.tasks ]
51
+ for tab, func in zip(tabs, func_of_tabs):
52
+ with tab:func()
53
+
54
+ def sidebar_elements(self):
55
+ actions = {"Project" : self.projects, "Team" : self.team }
56
+ with st.sidebar:
57
+ for label, action in actions.items():
58
+ st.header(label)
59
+ action()
60
+ st.divider()
61
+
62
+ def team(self):
63
+ teams_per_project = {"Projects": "Team1", "Projects2": "Team2", "Projects3": "Team3"}
64
+ st.write(teams_per_project[st.session_state.selected_project])
65
+ # st.image("static/2.png")
66
+
67
+ def tasks(self):
68
+ st.image("static/3.png")
69
+
70
+ def projects(self):
71
+ projects_available = ["Projects", "Projects2", "Projects3"]
72
+ st.session_state.selected_project = st.selectbox("Projects available", projects_available)
frontend_pages/__init__.py ADDED
@@ -0,0 +1,9 @@
 
 
 
 
 
 
 
 
 
 
1
+ import streamlit as st
2
+ import requests
3
+ import re
4
+ import os
5
+ import base64
6
+ from abc import ABC, abstractmethod
7
+ from functools import partial
8
+ from streamlit_calendar import calendar
9
+ from streamlit_extras.stylable_container import stylable_container
frontend_pages/__pycache__/BasePage.cpython-312.pyc ADDED
Binary file (1.77 kB). View file
 
frontend_pages/__pycache__/ChatModelPage.cpython-312.pyc ADDED
Binary file (7.97 kB). View file
 
frontend_pages/__pycache__/ConfigPage.cpython-312.pyc ADDED
Binary file (734 Bytes). View file
 
frontend_pages/__pycache__/Dashboard.cpython-312.pyc ADDED
Binary file (3.73 kB). View file
 
frontend_pages/__pycache__/__init__.cpython-312.pyc ADDED
Binary file (502 Bytes). View file
 
frontend_pages/__pycache__/load_css.cpython-312.pyc ADDED
Binary file (725 Bytes). View file
 
frontend_pages/__pycache__/modals.cpython-312.pyc ADDED
Binary file (7.8 kB). View file
 
frontend_pages/load_css.py ADDED
@@ -0,0 +1,10 @@
 
 
 
 
 
 
 
 
 
 
 
1
+ from . import st
2
+
3
+ def render_css(file_path):
4
+ with open(file_path, 'r') as file:
5
+ css_content = file.read()
6
+ st.markdown(f'<style>{css_content}</style>', unsafe_allow_html=True)
7
+
8
+ # Example usage
9
+ if __name__ == "__main__":
10
+ render_css('path_to_your_css_file.css')
frontend_pages/modals.py ADDED
@@ -0,0 +1,113 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import random
2
+ import docx
3
+ from PyPDF2 import PdfFileReader
4
+ import io
5
+
6
+ from . import st, base64, os, requests, partial
7
+ from .load_css import render_css
8
+
9
+ st.markdown(f'<style></style>', unsafe_allow_html=True)
10
+
11
+ def get_base64_image(image_path : str):
12
+ with open(image_path, "rb") as image_file:
13
+ return base64.b64encode(image_file.read()).decode()
14
+
15
+ @st.dialog("Create a Call")
16
+ def create_call_modal():
17
+ st.multiselect("People", ["Alice", "Bob", "Charlie"])
18
+ st.multiselect("Tasks", ["Task 1", "Task 2", "Task 3"])
19
+ st.text_area("Prompt")
20
+ buttons = [
21
+ ("submit", lambda _ : st.balloons()),
22
+ ("cancel", lambda _ : st.balloons())
23
+ ]
24
+ cols = st.columns(len(buttons))
25
+ for col, button in zip(cols, buttons):
26
+ with col:
27
+ if st.button(button[0]):
28
+ button[1]()
29
+
30
+ @st.dialog("Upload a Call")
31
+ def upload_call_modal_and_actions():
32
+ uploaded_file = st.file_uploader(
33
+ # "Import a videocall recording or its transcripts",
34
+ "Import a videocall recording transcript",
35
+ type=['.txt', '.doc', '.docx', '.pdf'],
36
+ # type=['.txt', '.doc', '.docx', '.pdf', '.mp4', '.wav', '.flac'],
37
+ accept_multiple_files=False
38
+ )
39
+ transcript_text = get_transcript_text(uploaded_file) if uploaded_file else ""
40
+ buttons = {
41
+ # "Crea minuta": minuta_action_from_uploaded_call,
42
+ # "Genera trascritto": transcript_action_from_uploaded_call,
43
+ "QA from transcripts": partial(qa_from_transcripts, Transcript = transcript_text),
44
+ "Generate Tasks from transcript": partial(create_tasks_action_from_uploaded_call_transcript, Transcript = transcript_text),
45
+ }
46
+ _ = buttons[st.selectbox("Choose an action", buttons.keys())]()
47
+
48
+ def minuta_action_from_uploaded_call():
49
+ if st.button("Crea minuta"):
50
+ st.download_button("Scarica minuta", data = "moc_minuta.txt")
51
+
52
+ def transcript_action_from_uploaded_call():
53
+ if st.button("Crea transcript"):
54
+ st.download_button("Scarica transcript", data = "moc_transcript.txt")
55
+
56
+ def get_transcript_text(uploaded_file):
57
+ if uploaded_file is not None:
58
+ file_extension = os.path.splitext(uploaded_file.name)[1].lower()
59
+ if file_extension == '.txt':
60
+ return get_text_from_txt(uploaded_file)
61
+ elif file_extension in ['.doc', '.docx']:
62
+ return get_text_from_doc(uploaded_file)
63
+ elif file_extension == '.pdf':
64
+ return get_text_from_pdf(uploaded_file)
65
+ return ""
66
+
67
+ def get_text_from_txt(uploaded_file):
68
+ return uploaded_file.read().decode("utf-8")
69
+
70
+ def get_text_from_doc(uploaded_file):
71
+ doc = docx.Document(uploaded_file)
72
+ return "\n".join([para.text for para in doc.paragraphs])
73
+
74
+ def get_text_from_pdf(uploaded_file):
75
+ reader = PdfFileReader(io.BytesIO(uploaded_file.read()))
76
+ text = ""
77
+ for page_num in range(reader.getNumPages()):
78
+ text += reader.getPage(page_num).extract_text()
79
+ return text
80
+
81
+
82
+ def qa_from_transcripts(Transcript : str):
83
+ Prompt = st.text_area("Prompt")
84
+ Transcript = st.text_area("Transcript")
85
+ Tasks = "\n\n".join(st.multiselect("Tasks", options = ["Task 1", "Task 2", "Task 3"]))
86
+ if st.button("QA from transcripts"):
87
+ response = requests.post(os.getenv("QA_TRANSCRIPT_ENDPOINT", "http://127.0.0.1:5000/transcript") ,
88
+ json = {
89
+ "prompt": Prompt,
90
+ "transcript" : Transcript or "",
91
+ "tasks": Tasks or [],
92
+ })
93
+ st.success(response.json())
94
+ return
95
+
96
+ def create_tasks_action_from_uploaded_call_transcript(Transcript : str):
97
+
98
+ if st.button("create_tasks"):
99
+ response = requests.post(os.getenv("QA_TRANSCRIPT_ENDPOINT", "http://127.0.0.1:5000/tasks/from_transcript") , json = {"transcript" : Transcript})
100
+ st.session_state.tasks = st.success(response.json())
101
+ return
102
+ if st.session_state.get('tasks'):
103
+ task = st.selectbox("Select a task", st.session_state.tasks)
104
+ task_matchmaking(task)
105
+
106
+ def task_matchmaking(task : str):
107
+ cols = st.columns(2)
108
+ with cols[0]:
109
+ st.markdown("### Task matchmaking")
110
+ with cols[1]:
111
+ st.multiselect("People", ["Alice", "Bob", "Charlie"])
112
+ if st.button("Assign"):
113
+ st.success("Task assigned")
requirements.txt ADDED
@@ -0,0 +1,140 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ altair==5.5.0
2
+ annotated-types==0.7.0
3
+ anyio==4.8.0
4
+ attrs==25.1.0
5
+ beautifulsoup4==4.13.3
6
+ blinker==1.9.0
7
+ cachetools==5.5.2
8
+ certifi==2025.1.31
9
+ charset-normalizer==3.4.1
10
+ click==8.1.8
11
+ colorama==0.4.6
12
+ contourpy==1.3.1
13
+ cycler==0.12.1
14
+ entrypoints==0.4
15
+ Faker==36.1.1
16
+ fastapi==0.115.8
17
+ favicon==0.7.0
18
+ fonttools==4.56.0
19
+ gitdb==4.0.12
20
+ GitPython==3.1.44
21
+ google-api-core==2.24.1
22
+ google-api-python-client==2.161.0
23
+ google-auth==2.38.0
24
+ google-auth-httplib2==0.2.0
25
+ google-auth-oauthlib==1.2.1
26
+ google-cloud==0.34.0
27
+ google-cloud-core==2.4.2
28
+ google-cloud-storage==3.0.0
29
+ google-cloud-vision==3.10.0
30
+ google-crc32c==1.6.0
31
+ google-resumable-media==2.7.2
32
+ googleapis-common-protos==1.68.0
33
+ gritql==0.1.5
34
+ grpcio==1.70.0
35
+ grpcio-status==1.70.0
36
+ h11==0.14.0
37
+ htbuilder==0.9.0
38
+ httpcore==1.0.7
39
+ httplib2==0.22.0
40
+ httpx==0.28.1
41
+ ibm-cos-sdk==2.13.6
42
+ ibm-cos-sdk-core==2.13.6
43
+ ibm-cos-sdk-s3transfer==2.13.6
44
+ ibm_watsonx_ai==1.2.8
45
+ idna==3.10
46
+ importlib_metadata==8.6.1
47
+ Jinja2==3.1.5
48
+ jmespath==1.0.1
49
+ jsonpatch==1.33
50
+ jsonpointer==3.0.0
51
+ jsonschema==4.23.0
52
+ jsonschema-specifications==2024.10.1
53
+ kiwisolver==1.4.8
54
+ langchain-cli==0.0.35
55
+ langchain-core==0.3.37
56
+ langchain-ibm==0.3.6
57
+ langgraph==0.2.74
58
+ langgraph-checkpoint==2.0.16
59
+ langgraph-sdk==0.1.53
60
+ langserve==0.3.1
61
+ langsmith==0.3.9
62
+ lomond==0.3.3
63
+ lxml==5.3.1
64
+ Markdown==3.7
65
+ markdown-it-py==3.0.0
66
+ markdownlit==0.0.7
67
+ MarkupSafe==3.0.2
68
+ matplotlib==3.10.0
69
+ mdurl==0.1.2
70
+ msgpack==1.1.0
71
+ narwhals==1.27.1
72
+ numpy==1.26.4
73
+ oauthlib==3.2.2
74
+ orjson==3.10.15
75
+ packaging==24.2
76
+ pandas==2.1.4
77
+ pillow==11.1.0
78
+ plotly==6.0.0
79
+ prometheus_client==0.21.1
80
+ proto-plus==1.26.0
81
+ protobuf==5.29.3
82
+ pyarrow==19.0.1
83
+ pyasn1==0.6.1
84
+ pyasn1_modules==0.4.1
85
+ pydantic==2.10.6
86
+ pydantic_core==2.27.2
87
+ pydeck==0.9.1
88
+ Pygments==2.19.1
89
+ pymdown-extensions==10.14.3
90
+ pyparsing==3.2.1
91
+ PyPDF2==3.0.1
92
+ python-dateutil==2.9.0.post0
93
+ python-docx==1.1.2
94
+ python-dotenv==1.0.1
95
+ pytz==2025.1
96
+ PyYAML==6.0.2
97
+ referencing==0.36.2
98
+ requests==2.32.2
99
+ requests-oauthlib==2.0.0
100
+ requests-toolbelt==1.0.0
101
+ rich==13.9.4
102
+ rpds-py==0.23.1
103
+ rsa==4.9
104
+ setuptools==75.8.0
105
+ shellingham==1.5.4
106
+ six==1.17.0
107
+ smmap==5.0.2
108
+ sniffio==1.3.1
109
+ soupsieve==2.6
110
+ SQLAlchemy==2.0.38
111
+ sse-starlette==1.8.2
112
+ st-annotated-text==4.0.2
113
+ st-theme==1.2.3
114
+ starlette==0.45.3
115
+ streamlit==1.42.2
116
+ streamlit-calendar==1.2.1
117
+ streamlit-camera-input-live==0.2.0
118
+ streamlit-card==1.0.2
119
+ streamlit-embedcode==0.1.2
120
+ streamlit-extras==0.5.5
121
+ streamlit-faker==0.0.3
122
+ streamlit-image-coordinates==0.1.9
123
+ streamlit-keyup==0.3.0
124
+ streamlit-toggle-switch==1.0.2
125
+ streamlit-vertical-slider==2.5.5
126
+ tabulate==0.9.0
127
+ tenacity==9.0.0
128
+ toml==0.10.2
129
+ tomlkit==0.13.2
130
+ tornado==6.4.2
131
+ typer==0.9.4
132
+ typing_extensions==4.12.2
133
+ tzdata==2025.1
134
+ uritemplate==4.1.1
135
+ urllib3==2.3.0
136
+ uvicorn==0.34.0
137
+ validators==0.34.0
138
+ wheel==0.45.1
139
+ zipp==3.21.0
140
+ zstandard==0.23.0
static/2.png ADDED

Git LFS Details

  • SHA256: f8ea1668fd0363a1770dd3e12dc96475bfadc8853d8e0b84d6bf1ca8269c57e3
  • Pointer size: 131 Bytes
  • Size of remote file: 126 kB
static/3.png ADDED

Git LFS Details

  • SHA256: 1f87a409aa0ce3d5c297f49b16b2f879feea06666d7fe566f3f3b1a81fac6d28
  • Pointer size: 131 Bytes
  • Size of remote file: 173 kB
static/NewCallButton.png ADDED
static/UploadCallButton.png ADDED