langchain / src /streamlit_app.py
pkraman06's picture
Update src/streamlit_app.py
86f3d5f verified
Raw
History Blame Contribute Delete
4.8 kB
import streamlit as st
from typing import TypedDict, List
from langchain_huggingface import ChatHuggingFace, HuggingFaceEndpoint
from langchain_core.prompts import ChatPromptTemplate
from langchain_community.tools import DuckDuckGoSearchRun
from langgraph.graph import StateGraph, END
# --- 1. STATE DEFINITION ---
class AgentState(TypedDict):
question: str
context: str
answer: str
trace: List[str]
# --- 2. DYNAMIC MODEL INITIALIZATION ---
def get_llm(token: str):
"""Initializes the LLM using the token provided in the UI."""
try:
llm = HuggingFaceEndpoint(
repo_id="Qwen/Qwen2.5-7B-Instruct",
task="text-generation",
max_new_tokens=512,
huggingfacehub_api_token=token,
)
return ChatHuggingFace(llm=llm, token=token)
except Exception as e:
st.error(f"Failed to initialize model: {str(e)}")
return None
# --- 3. NODE LOGIC ---
def router_node(state: AgentState, token: str):
llm = get_llm(token)
prompt = ChatPromptTemplate.from_template(
"Determine if this needs a web search for real-time info. "
"Reply ONLY with 'SEARCH' or 'KNOWLEDGE'.\nQuestion: {question}"
)
chain = prompt | llm
res = chain.invoke({"question": state["question"]})
decision = "SEARCH" if "SEARCH" in res.content.upper() else "KNOWLEDGE"
return {"context": decision, "trace": [f"πŸ” Router: Selected {decision} path"]}
def search_node(state: AgentState):
search = DuckDuckGoSearchRun()
results = search.run(state["question"])
return {"context": results, "trace": state["trace"] + ["🌐 Web Search: Results gathered"]}
def writer_node(state: AgentState, token: str):
llm = get_llm(token)
prompt = ChatPromptTemplate.from_template(
"Context: {context}\n\nProvide a detailed answer to: {question}"
)
chain = prompt | llm
res = chain.invoke({"context": state["context"], "question": state["question"]})
return {"answer": res.content, "trace": state["trace"] + ["✍️ Writer: Generated final response"]}
# --- 4. APP UI ---
st.set_page_config(page_title="LangChain Advanced Practice", layout="wide")
st.title("πŸ—οΈ LangGraph Practice Lab")
st.markdown("Build and test advanced autonomous workflows using open-source models.")
# Sidebar for Token Management
with st.sidebar:
st.header("Authentication")
user_token = st.text_input("Enter Hugging Face Token (hf_...)", type="password")
st.info("Get your token at: [hf.co/settings/tokens](https://huggingface.co/settings/tokens)")
if user_token:
st.success("Token provided!")
else:
st.warning("Please enter a token to unlock the agent.")
# Main Task Area
if user_token:
query = st.text_input("Task: Ask a question that requires reasoning or search")
if st.button("Execute Agentic Workflow"):
if query:
# Construct the Graph dynamically to inject the token
workflow = StateGraph(AgentState)
# Nodes
workflow.add_node("router", lambda x: router_node(x, user_token))
workflow.add_node("search", search_node)
workflow.add_node("writer", lambda x: writer_node(x, user_token))
# Edges
workflow.set_entry_point("router")
workflow.add_conditional_edges(
"router",
lambda x: "web" if x["context"] == "SEARCH" else "direct",
{"web": "search", "direct": "writer"}
)
workflow.add_edge("search", "writer")
workflow.add_edge("writer", END)
app = workflow.compile()
# Execution
with st.status("Agent Orchestrating...", expanded=True) as status:
final_state = app.invoke({"question": query, "trace": []})
st.subheader("Process Trace")
for step in final_state["trace"]:
st.write(step)
st.subheader("Final Output")
st.write(final_state["answer"])
status.update(label="Task Finished!", state="complete")
else:
st.error("Enter a query first.")
else:
st.info("πŸ‘ˆ Enter your Hugging Face token in the sidebar to start practicing.")
# Footer Practice Guide
st.divider()
with st.expander("πŸŽ“ Advanced Level Learning Goals"):
st.markdown("""
- **LCEL Implementation**: Watch how the `prompt | llm` chain is constructed.
- **State Control**: Observe how `AgentState` passes data between nodes.
- **Conditional Routing**: The router node uses the LLM as a logic gate.
- **Tool Integration**: DuckDuckGo search is used as a dynamic external tool.
""")