Skip to content

Commit 7350a27

Browse files
committed
Renewed reporting
1 parent 095d35a commit 7350a27

File tree

1 file changed

+181
-92
lines changed

1 file changed

+181
-92
lines changed

test2text/pages/report.py

Lines changed: 181 additions & 92 deletions
Original file line numberDiff line numberDiff line change
@@ -1,100 +1,189 @@
11
from itertools import groupby
2-
2+
import numpy as np
33
import streamlit as st
4-
from test2text.services.db import DbClient
5-
64

7-
def add_new_line(summary):
8-
return summary.replace("\n", "<br>")
5+
from test2text.services.db import DbClient
6+
from test2text.services.utils import unpack_float32
7+
from test2text.services.visualisation.visualize_vectors import minifold_vectors_2d, plot_vectors_2d
98

109

10+
1111
def make_a_report():
12-
st.header("Test2Text Report")
13-
14-
db = DbClient("./private/requirements.db")
15-
16-
st.subheader("Table of Contents")
17-
18-
data = db.conn.execute("""
19-
SELECT
20-
Requirements.id as req_id,
21-
Requirements.external_id as req_external_id,
22-
Requirements.summary as req_summary,
23-
24-
Annotations.id as anno_id,
25-
Annotations.summary as anno_summary,
26-
27-
AnnotationsToRequirements.cached_distance as distance,
28-
29-
TestCases.id as case_id,
30-
TestCases.test_script as test_script,
31-
TestCases.test_case as test_case
32-
FROM
33-
Requirements
34-
JOIN AnnotationsToRequirements ON Requirements.id = AnnotationsToRequirements.requirement_id
35-
JOIN Annotations ON Annotations.id = AnnotationsToRequirements.annotation_id
36-
JOIN CasesToAnnos ON Annotations.id = CasesToAnnos.annotation_id
37-
JOIN TestCases ON TestCases.id = CasesToAnnos.case_id
38-
ORDER BY
39-
Requirements.id, AnnotationsToRequirements.cached_distance, TestCases.id
40-
""")
41-
42-
current_annotations = {}
43-
current_test_scripts = set()
44-
45-
def write_requirement(req_id, req_external_id, req_summary,
46-
current_annotations: set[tuple], current_test_scripts: set):
47-
if req_id is None and req_external_id is None:
48-
return False
49-
50-
with st.expander(f"#{req_id} Requirement {req_external_id}"):
51-
st.subheader(f"Requirement {req_external_id}")
52-
st.html(f"<p>{add_new_line(req_summary)}</p>")
53-
st.subheader("Annotations")
54-
anno, summary, dist = st.columns(3)
55-
with anno:
56-
st.write("Annonation's id")
57-
with summary:
58-
st.write("Summary")
59-
with dist:
60-
st.write("Distance")
61-
for anno_id, anno_summary, distance in current_annotations:
62-
anno, summary, dist = st.columns(3)
63-
with anno:
64-
st.write(f"{anno_id}")
65-
with summary:
66-
st.html(
67-
f"{add_new_line(anno_summary)}"
68-
)
69-
with dist:
70-
st.write(round(distance, 2))
71-
72-
st.subheader("Test Scripts")
73-
for test_script in current_test_scripts:
74-
st.markdown(f"- {test_script}")
75-
76-
progress_bar = st.empty()
77-
rows = data.fetchall()
78-
if not rows:
79-
st.error("There is no data to inspect.\nPlease upload annotations.")
80-
return None
81-
max_progress = len(rows)
82-
index = 0
83-
for (req_id, req_external_id, req_summary), group in groupby(rows, lambda x: x[0:3]):
84-
current_annotations = set()
85-
current_test_scripts = set()
86-
index += 1
87-
for _, _, _, anno_id, anno_summary, distance, case_id, test_script, test_case in group:
88-
current_annotations.add((anno_id, anno_summary, distance))
89-
current_test_scripts.add(test_script)
90-
write_requirement(req_id=req_id, req_external_id=req_external_id, req_summary=req_summary,
91-
current_annotations=current_annotations, current_test_scripts=current_test_scripts)
92-
93-
94-
progress_bar.progress(round(index*100/max_progress), text="Processing...")
95-
progress_bar.empty()
96-
db.conn.close()
97-
9812

13+
st.header("Test2Text Report")
14+
15+
16+
db = DbClient("./private/requirements.db")
17+
18+
19+
def write_annotations(current_annotations: set[tuple]):
20+
anno, summary, dist = st.columns(3)
21+
with anno:
22+
st.write("Annonation's id")
23+
with summary:
24+
st.write("Summary")
25+
with dist:
26+
st.write("Distance")
27+
for anno_id, anno_summary, _, distance in current_annotations:
28+
anno, summary, dist = st.columns(3)
29+
with anno:
30+
st.write(f"{anno_id}")
31+
with summary:
32+
st.write(anno_summary)
33+
with dist:
34+
st.write(round(distance, 2))
35+
36+
with st.container(border=True):
37+
st.subheader("Filter requirements")
38+
with st.expander("🔍 Filters"):
39+
r_id, summary, embed = st.columns(3)
40+
with r_id:
41+
filter_id = st.text_input("ID", value="", key="filter_id")
42+
st.info("Filter by external ID")
43+
with summary:
44+
filter_summary = st.text_input("Text content", value="", key="filter_summary")
45+
st.info("Search concrete phrases using SQL like expressions")
46+
with embed:
47+
filter_embedding = st.text_input("Smart rearch", value="", key="filter_embedding")
48+
st.info("Search using embeddings")
49+
50+
where_clauses = []
51+
params = []
52+
53+
if filter_id.strip():
54+
where_clauses.append("Requirements.id = ?")
55+
params.append(filter_id.strip())
56+
57+
if filter_summary.strip():
58+
where_clauses.append("Requirements.summary LIKE ?")
59+
params.append(f"%{filter_summary.strip()}%")
60+
61+
# TODO embeddings фильтр не реализован
62+
if filter_embedding.strip():
63+
st.info("Фильтрация по embeddings не реализована в демо. Используйте другие фильтры.")
64+
65+
where_sql = ""
66+
if where_clauses:
67+
where_sql = f"WHERE {' AND '.join(where_clauses)}"
68+
69+
70+
with st.container(border=True):
71+
st.session_state.update({"req_form_submitting": True})
72+
sql = f"""
73+
SELECT
74+
Requirements.id as req_id,
75+
Requirements.external_id as req_external_id,
76+
Requirements.summary as req_summary
77+
FROM
78+
Requirements
79+
{where_sql}
80+
ORDER BY
81+
Requirements.id
82+
"""
83+
data = db.conn.execute(sql, params)
84+
85+
requirements_dict = {f"#{req_id} Requirement {req_external_id}": req_id for (req_id, req_external_id, _) in data.fetchall()}
86+
st.subheader("Choose 1 of filtered requirements")
87+
option = st.selectbox(
88+
"Choose a requirement to work with",
89+
requirements_dict.keys(),
90+
key="filter_req_id"
91+
)
92+
93+
if option:
94+
clause = "Requirements.id = ?"
95+
if clause in where_clauses:
96+
idx = where_clauses.index(clause)
97+
params.insert(idx, requirements_dict[option])
98+
else:
99+
where_clauses.append(clause)
100+
params.append(requirements_dict[option])
101+
where_sql = ""
102+
if where_clauses:
103+
where_sql = f"WHERE {' AND '.join(where_clauses)}"
104+
105+
sql = f"""
106+
SELECT
107+
Requirements.id as req_id,
108+
Requirements.external_id as req_external_id,
109+
Requirements.summary as req_summary,
110+
Requirements.embedding as req_embedding,
111+
112+
Annotations.id as anno_id,
113+
Annotations.summary as anno_summary,
114+
Annotations.embedding as anno_embedding,
115+
116+
AnnotationsToRequirements.cached_distance as distance,
117+
118+
TestCases.id as case_id,
119+
TestCases.test_script as test_script,
120+
TestCases.test_case as test_case
121+
FROM
122+
Requirements
123+
JOIN AnnotationsToRequirements ON Requirements.id = AnnotationsToRequirements.requirement_id
124+
JOIN Annotations ON Annotations.id = AnnotationsToRequirements.annotation_id
125+
JOIN CasesToAnnos ON Annotations.id = CasesToAnnos.annotation_id
126+
JOIN TestCases ON TestCases.id = CasesToAnnos.case_id
127+
{where_sql}
128+
ORDER BY
129+
Requirements.id, AnnotationsToRequirements.cached_distance, TestCases.id
130+
"""
131+
132+
rows = data.fetchall()
133+
if not rows:
134+
st.error("There is no data to inspect.\n"
135+
"Please upload annotations and requirements.")
136+
return None
137+
138+
st.subheader("Filter Test cases")
139+
140+
with st.expander("🔍 Filters"):
141+
radius, limit = st.columns(2)
142+
with radius:
143+
filter_radius = st.number_input("Insert a radius", key="filter_radius")
144+
st.info("Max distance to annotation")
145+
with limit:
146+
filter_limit = st.text_input("Limit", value="", key="filter_limit")
147+
st.info("Limit of selected test cases")
148+
149+
for (req_id, req_external_id, req_summary, req_embedding), group in groupby(rows, lambda x: x[0:4]):
150+
with st.container(border=True):
151+
st.subheader(f" Inspect Requirement {req_external_id}")
152+
st.write(req_summary)
153+
current_test_cases = dict()
154+
for _, _, _, _, anno_id, anno_summary, anno_embedding, distance, case_id, test_script, test_case in group:
155+
current_annotation = current_test_cases.get(test_case, set())
156+
current_test_cases.update({test_case: current_annotation})
157+
current_test_cases[test_case].add((anno_id, anno_summary, anno_embedding, distance))
158+
159+
t_cs, anno, viz = st.columns(3)
160+
with t_cs:
161+
with st.container(border=True):
162+
st.write("Test Cases")
163+
st.markdown("""
164+
<style>
165+
.stRadio > div {
166+
max-width: 350px;
167+
word-break: break-word;
168+
white-space: pre-line;
169+
}
170+
</style>
171+
""", unsafe_allow_html=True)
172+
st.radio("", current_test_cases.keys(), key="radio_choice")
173+
if st.session_state["radio_choice"]:
174+
with anno:
175+
with st.container(border=True):
176+
st.write("Annotations")
177+
write_annotations(current_annotations=current_test_cases[st.session_state["radio_choice"]])
178+
179+
with viz:
180+
with st.container(border=True):
181+
pass
182+
#req_dot = np.array(unpack_float32(req_embedding)) TODO
183+
#plot_vectors_2d(minifold_vectors_2d(np.array([req_dot])), "Requirements")
184+
185+
db.conn.close()
186+
187+
99188
if __name__ == "__main__":
100-
make_a_report()
189+
make_a_report()

0 commit comments

Comments
 (0)