Spaces:
Runtime error
Runtime error
File size: 7,372 Bytes
4f07f72 cc9a95f d934e05 cc9a95f 88be29a d934e05 7c479ac 59df961 cc9a95f 03dc960 88be29a dd4879b 88be29a 57b94ca 88be29a 57b94ca 88be29a 57b94ca 88be29a 57b94ca 7c479ac 57b94ca 88be29a 03dc960 cc9a95f 2db4636 06b78a1 cc46ec6 cc9a95f 03dc960 cc9a95f 7c479ac cc9a95f 7c479ac cc9a95f 1262b99 cc9a95f aff284c cc9a95f d934e05 cc9a95f 03dc960 cc9a95f 03dc960 cc9a95f 03dc960 cc9a95f 03dc960 cc9a95f 03dc960 88be29a cc9a95f |
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 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 |
"""
This page displays the architectures which have been configured in the system and lets
users interact with them. If users choose to interact with a single architecture they get
a more detailed breakdown of the architecture flow, if they choose to view side by side results
they get to see just the time taken and the response.
"""
import pandas as pd
import streamlit as st
from time import time
from src.st_helpers import st_setup
from src.data_synthesis.test_question_generator import generate_question
from src.common import img_dir, escape_dollars, generate_group_tag
from src.architectures import *
COMPARE = "Side by side compare" # Constant value to use for the UI to select a side by side architecture comparison
def show_side_by_side() -> None:
"""
Display a selector to pick a number of architectures to compare side by side and then the
chat interaction box per architecture to see the response timing and response.
"""
# Build the layout structure
st.divider()
header_container = st.container()
arch_outer_container = st.container()
# Build header
with header_container:
st.write("### Side by side comparison of architectures")
st.write('Enter a question below to have it sent to the selected architectures to compare timing and response.')
options = [a.name for a in Architecture.architectures]
selected_archs = st.multiselect("Select architectures to use", options=options, default=options)
if len(selected_archs) == 0:
st.write("To get started select some architectures to compare")
else:
prompt = st.chat_input("Ask a question")
if st.button("Or press to ask a random question"):
prompt = generate_question()
if prompt:
st.write(f"**Question:** {prompt}")
# Now build the columns
if len(selected_archs) > 0:
with arch_outer_container:
arch_cols = st.columns(len(selected_archs))
if prompt:
# Build columns per architecture
for i, a in enumerate(selected_archs):
with arch_cols[i]:
st.write(f'#### {a}')
# Now dispatch the messages per architecture
group_tag = generate_group_tag()
for i, a in enumerate(selected_archs):
request = ArchitectureRequest(query=prompt)
arch = Architecture.get_architecture(a)
with arch_cols[i]:
with st.spinner('Architecture processing request'):
start = time()
arch(request, trace_tags=["UI", "SideBySideCompare", group_tag])
elapsed_in_s = (int((time() - start) * 10))/10 # round to 1dp in seconds
st.write('##### Timing')
st.write(f'Request took **{elapsed_in_s}s**')
st.write('##### Response')
st.write(request.response)
else:
# Build columns per architecture for display only
for i, a in enumerate(selected_archs):
with arch_cols[i]:
st.write(f'#### {a}')
def display_architecture_in_container(arch, arch_container) -> None:
with arch_container:
st.divider()
st.write(f'### {arch.name}')
st.write('#### Architecture description')
st.write(arch.description)
if arch.img is not None:
img = os.path.join(img_dir, arch.img)
st.image(img, caption=f'{arch.name} As Built', width=1000)
table_data = []
for j, s in enumerate(arch.steps, start=1):
table_data.append(
[j, s.__class__.__name__, s.description, s.config_description()]
)
table_cols = ['Step', 'Name', 'Description', 'Config details']
st.write('#### Architecture pipeline steps')
st.table(pd.DataFrame(table_data, columns=table_cols))
def display_architecture_chat_in_container(arch, chat_container) -> None:
with chat_container:
st.write(f"### Chat with {arch.name}")
st.write("Note this is a simple single query through the relevant architecture. This is just a sample so you can interact with it and does not manage a chat session history.")
prompt = st.chat_input("Ask a question")
if st.button("Or press to ask a random question"):
prompt = generate_question()
chat_col, trace_col, request_col = st.columns([3, 2, 2])
with chat_col:
with st.chat_message("assistant"):
st.write("Chat with me in the box below")
if prompt:
with chat_col:
with st.chat_message("user"):
st.write(prompt)
request = ArchitectureRequest(query=prompt)
trace = arch(request, trace_tags=["UI", "SingleArchTest"])
with st.chat_message("assistant"):
st.write(escape_dollars(request.response))
with trace_col:
st.write("#### Architecture Trace")
st.markdown(trace.as_markdown())
with request_col:
st.write("#### Full Request/Response")
st.markdown(request.as_markdown())
def show_architecture(architecture: str) -> None:
"""
Streamlit render an architecture details and the
ability to interact with the architecture
:param architecture: the name of the architecture to output
"""
arch = Architecture.get_architecture(architecture)
# Segment into two containers for organisation
arch_container = st.container()
chat_container = st.container()
display_architecture_in_container(arch, arch_container)
display_architecture_chat_in_container(arch, chat_container)
def show_sub_header() -> None:
"""
Write a subheader to the page depending on how many architectures are configured
"""
arch_count = len(Architecture.architectures)
if arch_count == 1:
st.write('### 1 Architecture available')
else:
st.write(f'### {arch_count} Architectures available')
def show_reload_button() -> None:
"""
Shows a button to reload the architectures and force them to reload if clicked
"""
if st.button("Force reload of architecture configs"):
Architecture.load_architectures(force_reload=True)
def get_user_selected_architecture() -> Optional[str]:
"""
Display a picker of all the architectures plus the option to do a side by side compare
"""
arch_names = [a.name for a in Architecture.architectures]
arch_names.append(COMPARE)
return st.radio(label="Available architectures", label_visibility="hidden", options=arch_names, index=None)
if st_setup('LLM Arch'):
st.write("# LLM Architectures")
Architecture.load_architectures()
show_sub_header()
show_reload_button()
selected_arch = get_user_selected_architecture()
if selected_arch is None:
st.info('Select an architecture from above to see details and interact with it')
elif selected_arch == COMPARE:
show_side_by_side()
else:
show_architecture(selected_arch)
|