Files
wehub-resource-sync 86db9aae8e
Documentation / build (push) Has been cancelled
Documentation / deploy (push) Has been cancelled
chore: import upstream snapshot with attribution
2026-07-13 13:34:55 +08:00

206 lines
7.6 KiB
Python

from llmware.gguf_configs import GGUFConfigs
from llmware.library import Library
from llmware.prompts import Prompt
from llmware.retrieval import Query
from llmware.models import ModelCatalog
import streamlit as st
import os
import sys
sys.path.insert(0, os.getcwd())
from Utils import get_stored_files, get_stored_libraries
GENERAL_PURPOSE_MODEL = 'phi-3-gguf'
RAG_MODEL = 'bling-phi-3-gguf'
RERANKER_MODEL = 'jina-reranker-turbo'
ACCOUNT_NAME = 'lecture_tool'
#
# Calls the GENERAL_PURPOSE_MODEL defined above on the specified question.
#
@st.cache_data(show_spinner=False)
def prompt_general_question(question):
# Set limit on output length
GGUFConfigs().set_config("max_output_tokens", 1000)
# Load in appropriate model
prompter = Prompt().load_model(GENERAL_PURPOSE_MODEL, max_output=999)
# Prompt the model with the question
print('\nupdate: performing prompt')
response = prompter.prompt_main(question)
print('\nupdate: llm response - ', response)
return response['llm_response']
#
# Calls the RAG_MODEL defined above to answer questions about lecture content.
#
# Accesses the library_name specified to pass either the entire library or a
# specified file from the library as source for reranking.
#
# RERANKER_MODEL defined above generates a list of the most relevant text blocks
# based on the question (prompt) with semantic reranking.
# These are passed as source to the RAG_MODEL for inference along with the
# question (prompt).
#
@st.cache_data(show_spinner=False)
def prompt_question_about_content_with_reranking(question, library_name, filename, topic=None):
# Load in appropriate library
library = Library().load_library(library_name, account_name=ACCOUNT_NAME)
print('\nupdate: library card - ', library.get_library_card())
# Create Query object
query = Query(library)
# Load in appropriate models
rag_prompter = Prompt().load_model(RAG_MODEL, temperature=0.0, sample=False)
reranker_model = ModelCatalog().load_model(RERANKER_MODEL, temperature=0.0, sample=False)
# Access appropriate text blocks if all files are to be selected
if filename == 'Select all files':
print('\nupdate: all files selected')
# Access entire library since no topic is specified
if topic is None or topic == '':
print('\nupdate: no topic provided, adding entire library as source')
query_results = query.get_whole_library()
# Change key in query results for compatibility with RAG call
for result in query_results:
result['text'] = result['text_search']
del result['text_search']
print('\nupdate: correct library chunks - ', query_results)
# Access limited blocks from library based on topic specified
else:
# Perform text_query with the topic
print('\nupdate: topic provided, performing text query for topic')
query_results = query.text_query(topic)
print('\nupdate: topic chunks - ', query_results)
# Access appropriate text chunks if a specific file is selected
else:
print('\nupdate: file selected - ', filename)
# Access all blocks for the specified file since no topic is specified
if topic is None or topic == '':
print('\nupdate: no topic provided, adding entire library as source')
# Filter out only the blocks that correspond to the desired file
query_results = query.apply_custom_filter(query.get_whole_library(), {'file_source': filename})
# Change key in query results for compatibility with RAG call
for result in query_results:
result['text'] = result['text_search']
del result['text_search']
print('\nupdate: correct library chunks - ', query_results)
# Access limited blocks from library based on topic and file specified
else:
# Perform a text query for the topic, then filter based on filename
print('\nupdate: topic provided, performing text query for topic')
query_results = query.apply_custom_filter(query.text_query(topic), {'file_source': filename})
print('\nupdate: topic chunks - ', query_results)
if len(query_results) == 0:
print('\nupdate: sources are empty')
return 'No result found. Please check to ensure your topic and file are accurate.', None, None
# Perform semantic reranking to get relevant text blocks
print('\nupdate: performing semantic ranking')
reranker_output = reranker_model.inference(question, query_results, top_n=10, relevance_threshold=0.2)
# Use only the 3 most relevant blocks if more are returned from rereanking
use_top = 3
if len(reranker_output) > use_top:
reranker_output = reranker_output[:use_top]
print('\nupdate: reranker output - ')
for i, source in enumerate(reranker_output):
print(i, ' - ', source)
# Pass relevant blocks from reranking as source for RAG call
sources = rag_prompter.add_source_query_results(reranker_output)
print('\nupdate: sources - ', sources)
# Perform RAG call with the question
print('\nupdate: performing prompt')
response = rag_prompter.prompt_with_source(question)
# Store metadata about the RAG call for later use
stats = rag_prompter.evidence_comparison_stats(response)
ev_source = rag_prompter.evidence_check_sources(response)
# Output LLM response
for i, resp in enumerate(response):
print('\nupdate: llm response - ', resp)
print('\nupdate: compare with evidence - ', stats[i]['comparison_stats'])
print('\nupdate: sources - ', ev_source[i]['source_review'])
# Clear the source so the next call does not reuse previous source
rag_prompter.clear_source_materials()
source_file = response[0]['source_review'][0]['source'] if 'source_review' in response[0] and len(response[0]['source_review']) > 0 else None
return response[0]['llm_response'], response[0]['evidence'], source_file
#
# Main block for GUI logic.
#
if __name__ == '__main__':
st.title('Ask questions about lecture content')
st.write('### Question info')
question_type = st.selectbox(
'Select the type of question:',
('Question about Content', 'General Question')
)
question = st.text_input('Enter your question:')
if question_type == 'Question about Content':
st.write('### Prompt info')
topic = st.text_input('Optionally enter a topic:')
library_name = st.selectbox(
'Select the library:',
tuple(get_stored_libraries())
)
if library_name:
filename = st.selectbox(
'Select the file:',
tuple(['Select all files'] + get_stored_files(library_name))
)
if st.button('Prompt'):
if question_type == 'General Question':
with st.spinner('Processing request... don\'t leave this page!'):
response = prompt_general_question(question)
st.write('### Response')
st.write(response)
elif question_type == 'Question about Content':
with st.spinner('Processing request... don\'t leave this page!'):
response, evidence, source = prompt_question_about_content_with_reranking(question, library_name, filename, topic)
st.write('### Response')
st.write(response)
if evidence:
st.write('### Evidence')
st.write('"' + evidence + '"')
if source:
st.write('### File source')
st.write(source)