Skip to content

Commit 1be69c0

Browse files
authored
added disclaimer to chat and models pages, with test cases (#191)
1 parent 0bd22c2 commit 1be69c0

File tree

11 files changed

+208
-0
lines changed

11 files changed

+208
-0
lines changed

src/client/content/api_server.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
import client.utils.st_common as st_common
1818
import client.utils.client as client
1919
import client.utils.api_call as api_call
20+
from client.utils.st_footer import remove_footer
2021
import common.logging_config as logging_config
2122
from common.schema import ClientIdType
2223

@@ -66,6 +67,7 @@ def server_restart() -> None:
6667
#####################################################
6768
async def main() -> None:
6869
"""Streamlit GUI"""
70+
remove_footer()
6971
st_common.set_server_state()
7072
st.header("API Server")
7173
st.write("Access with your own client.")

src/client/content/chatbot.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
from streamlit import session_state as state
1717

1818
import client.utils.st_common as st_common
19+
from client.utils.st_footer import render_chat_footer
1920
import client.utils.client as client
2021
from client.content.config.models import get_models
2122
import common.logging_config as logging_config
@@ -116,6 +117,7 @@ async def main() -> None:
116117
st.write(content)
117118

118119
sys_prompt = state.user_settings["prompts"]["sys"]
120+
render_chat_footer()
119121
if human_request := st.chat_input(
120122
f"Ask your question here... (current prompt: {sys_prompt})",
121123
accept_file=True,

src/client/content/config/databases.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
import client.utils.st_common as st_common
2020
import common.logging_config as logging_config
2121
from common.schema import SelectAIProfileType
22+
from client.utils.st_footer import remove_footer
2223

2324
logger = logging_config.logging.getLogger("client.content.config.database")
2425

@@ -120,6 +121,7 @@ def update_selectai(sai_new_df: pd.DataFrame, sai_old_df: pd.DataFrame) -> None:
120121
#####################################################
121122
def main() -> None:
122123
"""Streamlit GUI"""
124+
remove_footer()
123125
st.header("Database", divider="red")
124126
st.write("Configure the database used for Vector Storage and SelectAI.")
125127
try:

src/client/content/config/models.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020

2121
import streamlit as st
2222
from streamlit import session_state as state
23+
from client.utils.st_footer import render_models_footer
2324

2425
import client.utils.api_call as api_call
2526

@@ -322,6 +323,7 @@ def main() -> None:
322323
)
323324
if st.button(label="Add", type="primary", key="add_embed_model"):
324325
edit_model(model_type="embed", action="add")
326+
render_models_footer()
325327

326328

327329
if __name__ == "__main__" or "page.py" in inspect.stack()[1].filename:

src/client/content/config/oci.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
import client.utils.api_call as api_call
2121
import client.utils.st_common as st_common
2222
from client.content.config.models import get_models
23+
from client.utils.st_footer import remove_footer
2324

2425
import common.logging_config as logging_config
2526

@@ -138,6 +139,7 @@ def patch_oci_genai(
138139
#####################################################
139140
def main() -> None:
140141
"""Streamlit GUI"""
142+
remove_footer()
141143
st.header("Oracle Cloud Infrastructure", divider="red")
142144
st.write("Configure OCI for Object Storage Access and OCI GenAI Services.")
143145
try:

src/client/content/config/settings.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
from client.content.config.oci import patch_oci, get_oci
2929
from client.content.tools.prompt_eng import patch_prompt, get_prompts
3030
from client.content.config.models import patch_model, get_models
31+
from client.utils.st_footer import remove_footer
3132

3233
# Schema
3334
from common.schema import Model
@@ -269,6 +270,7 @@ def spring_ai_zip(provider, ll_model):
269270
#####################################################
270271
def main():
271272
"""Streamlit GUI"""
273+
remove_footer()
272274
st.header("Client Settings", divider="red")
273275
get_models(model_type="ll", force=True)
274276
get_models(model_type="embed", force=True)

src/client/content/testbed.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
from client.content.config.models import get_models
1919
import client.utils.st_common as st_common
2020
import client.utils.api_call as api_call
21+
from client.utils.st_footer import remove_footer
2122

2223
import common.logging_config as logging_config
2324

@@ -233,6 +234,7 @@ def qa_update_gui(qa_testset: list) -> None:
233234
#############################################################################
234235
def main():
235236
"""Streamlit GUI"""
237+
remove_footer()
236238
db_avail = st_common.is_db_configured()
237239
if not db_avail:
238240
logger.debug("Testbed Disabled (Database not configured)")

src/client/content/tools/prompt_eng.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
import client.utils.st_common as st_common
1919
import client.utils.api_call as api_call
2020
import common.logging_config as logging_config
21+
from client.utils.st_footer import remove_footer
2122

2223
logger = logging_config.logging.getLogger("client.tools.prompt_eng")
2324

@@ -66,6 +67,7 @@ def patch_prompt(category: str, name: str, prompt: str) -> None:
6667
#############################################################################
6768
def main():
6869
"""Streamlit GUI"""
70+
remove_footer()
6971
st.header("Prompt Engineering")
7072
st.write("Select which prompts to use and their instructions. Currently selected prompts are used.")
7173
try:

src/client/content/tools/split_embed.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
from client.content.config.models import get_models
2020
import client.utils.api_call as api_call
2121
import client.utils.st_common as st_common
22+
from client.utils.st_footer import remove_footer
2223
from common.schema import DistanceMetrics, IndexTypes, DatabaseVectorStorage
2324
import common.functions
2425
import common.help_text as help_text
@@ -109,6 +110,7 @@ def update_chunk_size_input() -> None:
109110
#############################################################################
110111
def main() -> None:
111112
"""Streamlit GUI"""
113+
remove_footer()
112114
db_avail = st_common.is_db_configured()
113115
if not db_avail:
114116
logger.debug("Embedding Disabled (Database not configured)")

src/client/utils/st_footer.py

Lines changed: 116 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,116 @@
1+
"""
2+
Copyright (c) 2024, 2025, Oracle and/or its affiliates.
3+
Licensed under the Universal Permissive License v1.0 as shown at http://oss.oracle.com/licenses/upl.
4+
"""
5+
# spell-checker:ignore streamlit, selectbox, mult, iloc, selectai, isin
6+
7+
import streamlit as st
8+
import streamlit.components.v1 as components
9+
10+
FOOTER_STYLE = """
11+
<style>
12+
.footer-container, .footer {
13+
text-align: center !important;
14+
}
15+
.footer-container {
16+
padding-top: 0.5rem !important;
17+
}
18+
.footer {
19+
padding: 2rem 0 0.5rem 0 !important;
20+
}
21+
.footer-container p, .footer p {
22+
font-size: 12px !important;
23+
color: #8E8E93 !important;
24+
margin: 0 !important;
25+
padding: 0 !important;
26+
}
27+
.footer-container a, .footer a {
28+
color: #8E8E93 !important;
29+
text-decoration: underline !important;
30+
}
31+
</style>
32+
"""
33+
34+
# --- SHARED LOGIC ---
35+
def _inject_footer(selector, insertion_method, footer_html, cleanup_styles=True):
36+
"""
37+
Shared footer injection logic with optional style cleanup.
38+
39+
Args:
40+
selector: CSS selector to find the injection target
41+
insertion_method: 'afterend' or 'beforebegin'
42+
footer_html: Complete HTML content to inject
43+
cleanup_styles: Whether to apply padding/margin cleanup to target element
44+
"""
45+
js_safe_html = footer_html.replace("`", "\\`").replace("\n", "")
46+
cleanup_js = """
47+
target.style.paddingBottom = '0';
48+
target.style.marginBottom = '0';""" if cleanup_styles else ""
49+
js_code = f"""
50+
<script>
51+
const checkReady = setInterval(() => {{
52+
const target = parent.document.querySelector('{selector}');
53+
if (target && !parent.document.getElementById('page-footer')) {{
54+
clearInterval(checkReady);
55+
{cleanup_js}
56+
target.insertAdjacentHTML('{insertion_method}', `{js_safe_html}`);
57+
}}
58+
}}, 100);
59+
setTimeout(() => clearInterval(checkReady), 3000);
60+
</script>
61+
"""
62+
components.html(js_code, height=0)
63+
64+
65+
# --- FUNCTION 1: The Cleanup Crew ---
66+
def remove_footer():
67+
"""
68+
Injects simple JavaScript to find and remove any existing footer.
69+
This MUST be called at the TOP of every page in your app.
70+
"""
71+
js_code = """
72+
<script>
73+
const footer = parent.document.getElementById('page-footer');
74+
if (footer) {
75+
footer.remove();
76+
}
77+
</script>
78+
"""
79+
components.html(js_code, height=0)
80+
81+
82+
# --- FUNCTION 2: The Chat Page Footer ---
83+
def render_chat_footer():
84+
"""
85+
Standardized footer for chat pages.
86+
"""
87+
footer_html = f"""
88+
{FOOTER_STYLE}
89+
<div class="footer-container" id="page-footer">
90+
<p>LLMs can make mistakes. Always verify important information.</p>
91+
</div>
92+
"""
93+
_inject_footer(
94+
selector='[data-testid="stBottomBlockContainer"]',
95+
insertion_method='afterend',
96+
footer_html=footer_html
97+
)
98+
99+
100+
# --- FUNCTION 3: The Models Page Footer ---
101+
def render_models_footer():
102+
"""
103+
Standardized footer for models pages.
104+
"""
105+
footer_html = f"""
106+
{FOOTER_STYLE}
107+
<div class="footer" id="page-footer">
108+
<p>LLMs can make mistakes. Always verify important information.</p>
109+
</div>
110+
"""
111+
_inject_footer(
112+
selector='[data-testid="stAppIframeResizerAnchor"]',
113+
insertion_method='beforebegin',
114+
footer_html=footer_html,
115+
cleanup_styles=False
116+
)

0 commit comments

Comments
 (0)