mistral-entity-extractor / src /streamlit_app.py
ksckaushal's picture
Update src/streamlit_app.py
9ea8980 verified
Raw
History Blame Contribute Delete
4.6 kB
import streamlit as st
from llama_cpp import Llama
from huggingface_hub import hf_hub_download, list_repo_files
# Set up clean, professional page layout
st.set_page_config(page_title="Mistral Entity Extractor", layout="wide", page_icon="πŸ›’")
# 1. Dynamically find and cache the GGUF model loading sequence
@st.cache_resource
def load_quantized_model():
# Your exact public model repository path
repo_id = "ksckaushal/Mistral-Entity-Extraction"
with st.spinner("Initializing system and loading optimized Mistral GGUF model from Hugging Face Hub..."):
try:
# Look up files in your public repo to find the .gguf file dynamically
files = list_repo_files(repo_id)
gguf_filename = next((f for f in files if f.endswith('.gguf')), None)
if not gguf_filename:
st.error("Error: Could not find a file ending in '.gguf' in your repository.")
return None
# Download the GGUF file
model_path = hf_hub_download(repo_id=repo_id, filename=gguf_filename)
# Load the model utilizing the free tier's 2 available vCPU threads
llm = Llama(model_path=model_path, n_ctx=2048, n_threads=2)
return llm
except Exception as e:
st.error(f"Failed to load model: {str(e)}")
return None
# Initialize the model
llm = load_quantized_model()
# 2. Define the Alpaca Prompt Template used during your fine-tuning
ALPACA_PROMPT = """Below is an instruction that describes a task, paired with an input that provides further context. Write a response that appropriately completes the request.
### Instruction:
{}
### Input:
{}
### Response:
{}"""
# 3. Build a high-quality, recruiter-friendly Dashboard UI
st.title("πŸ›’ Fine-Tuned Mistral Entity Extractor")
st.markdown(
"""
**Developer Portfolio Project**
This production-ready application serves a fine-tuned **Mistral-7B** LLM optimized via **Q5_K_M GGUF quantization**
to extract custom attributes and entities from raw text into clean, structured JSON format.
*Running 100% serverless on commodity free-tier CPU hardware using Llama.cpp.*
"""
)
st.write("---")
# Split user interface into 2 proportional columns
col1, col2 = st.columns([1, 1])
with col1:
st.subheader("πŸ“‹ Input Dataset")
review_input = st.text_area(
label="Paste laptop or product review text below:",
height=250,
placeholder="Example: 'The battery life on this Dell Inspiron is spectacular, reaching almost 10 hours, but the cooling fan is terribly loud under load...'"
)
# Custom engineering settings showcased to recruiters
with st.expander("βš™οΈ Inference Parameters (Hyperparameters)"):
temp = st.slider("Temperature", min_value=0.0, max_value=1.0, value=0.1, step=0.1,
help="Lower temperatures yield highly deterministic, rigidly structured JSON outputs.")
max_tokens = st.slider("Max New Tokens", min_value=64, max_value=1024, value=512, step=64)
submit_btn = st.button("Extract Structured Entities", type="primary", use_container_width=True)
with col2:
st.subheader("⚑ Structured Output (JSON)")
if submit_btn:
if review_input.strip() and llm is not None:
# Set the prompt instruction
instruction = "Extract entities in the input review in a JSON format."
formatted_prompt = ALPACA_PROMPT.format(instruction, review_input, "")
with st.spinner("Processing text weights on CPU..."):
try:
# Run inference via Llama.cpp
raw_output = llm(
formatted_prompt,
max_tokens=max_tokens,
temperature=temp,
stop=["###", "\n\n"] # Strict generation boundary handling
)
extracted_json = raw_output['choices'][0]['text'].strip()
# Display output beautifully as a code block
st.success("Extraction Complete!")
st.code(extracted_json, language="json")
except Exception as e:
st.error(f"Inference Engine Error: {str(e)}")
elif llm is None:
st.error("Model engine failed to initialize. Review the Hugging Face space logs.")
else:
st.warning("Please provide an input review text first!")