Part 2. Deploying the web app to Streamlit
Introduction
In this post we are going to take the SQLite database with the searchable index we created in Part 1 and use it as the search engine for a web app we are going to deploy to Streamlit.
So we are going to be able to search over the entire fastai channel.
The Python file was created with a Jupyter Notebook using nbdev.
The web app is just like this one: Full-Text Search Engine for fastai Youtube Chanel
References
If you want to get deeper, I encourage you to read these articles:
Creating app.py
#|export
import streamlit as st
import sqlite3
#| export
= '/mnt/m/datamatica/posts/full-text-search-fastai-youtube-channel/'
db_path
try:
= sqlite3.connect(db_path + 'fastai_yt.db')
db except:
= sqlite3.connect('fastai_yt.db')
db
= db.cursor() cur
#| export
= cur.execute('SELECT playlist_id, playlist_name FROM playlist').fetchall()
playlist = cur.execute('SELECT video_id, video_name FROM video').fetchall()
video = {p: n for p, n in playlist}
playlist = {p: n for p, n in video}
video = list(playlist.values())
pl_sel = {v:k for k,v in playlist.items()} pl_to_id
#| export
'Full-Text Search fastai Youtube Playlists')
st.title(
# https://discuss.streamlit.io/t/select-all-on-a-streamlit-multiselect/9799/2
= st.checkbox("Select all Playlists",
all_options ='sel_all', value=True)
key
= st.container()
container if all_options:
= container.multiselect("Select one or more Playlist(s):",
sel_options =True)
pl_sel, disabledelse:
= container.multiselect("Select one or more Playlist(s):",
sel_options
pl_sel, pl_sel)
if all_options: options = list(playlist.values())
else: options = sel_options
'Selected playlist(s):', options) st.write(
#| export
def get_query(q, limit):
= 'text'
search_in
if not( len(options)==len(pl_sel) or len(options)==0 ):
= 'transcriptions_fts'
search_in = '(playlist_id: '
q_pl for pl in options:
= ' OR ' if pl != options[-1] else ')'
end = q_pl + f'"{pl_to_id[pl]}"' + end
q_pl
= f"(text: {q}) AND " + q_pl
q
= f"""
query SELECT *, HIGHLIGHT(transcriptions_fts, 3, '[', ']')
FROM transcriptions_fts WHERE {search_in} MATCH '{q}' ORDER BY rank
LIMIT "{limit}"
"""
return query
with st.form("Input"):
= st.text_area("Search query: \ne.g. «fastc*», «fastcore OR paral*»", height=1, max_chars=None)
queryText = st.slider("Number of results:", min_value=5, max_value=20)
limit_val = st.form_submit_button('Search')
btnResult
if btnResult:
if not queryText:
'Please enter a search query.')
st.text(else:
try:
'Search query generated:')
st.text(# run query
'*', '\*'))
st.write(get_query(queryText, limit_val).replace(= cur.execute(get_query(q=queryText, limit=limit_val)).fetchall()
res 'Search results (click to go to YouTube):')
st.text(
= (' \n '.join([' \n '.join([
res_md f"{i}.- Playlist: `{playlist[each[0]]}`, Video: `{video[each[1]]}`",
f"Caption: '...[{each[4].replace('[','**'
.replace(']','**')}](https://youtu.be/{each[1]}?t={str(int(each[2]))})...'",
)'\n'])
for i, each in enumerate(res)
]))
st.markdown(res_md)except:
'Invalid search query.') st.text(
#| hide
from nbdev.export import nb_export
'_Deploy_Search_Engine_Streamlit.ipynb', lib_path='.', name='app') nb_export(