import os import time import streamlit as st from smolagents import CodeAgent, HfApiModel, tool from huggingface_hub import InferenceClient import requests from bs4 import BeautifulSoup # Retrieve Hugging Face token hf_token = os.getenv("HF_TOKEN") if not hf_token: raise ValueError("Hugging Face token not found. Please set it in the environment or Streamlit secrets.") # Initialize the Hugging Face Inference client client = InferenceClient(token=hf_token) # Custom tools for SmolAgents @tool def search_harry_potter_lore(query: str) -> str: """Search for Harry Potter-related lore or facts across the entire Harry Potter Fandom site. Args: query: A specific question or topic about Harry Potter lore. Returns: A concise and informative response based on the query. """ headers = {"User-Agent": "Mozilla/5.0"} # Construct the search URL for the Harry Potter Fandom site. search_url = f"https://harrypotter.fandom.com/wiki/Special:Search?query={query}" try: # Fetch the search results page. search_response = requests.get(search_url, headers=headers) if search_response.status_code != 200: return f"Error: Received status code {search_response.status_code} from search." search_soup = BeautifulSoup(search_response.text, 'html.parser') # Look for the first link that appears to be an article. article_url = None for a in search_soup.find_all("a", href=True): href = a["href"] # We want links that start with /wiki/ but skip those that contain "Special:" if href.startswith("/wiki/") and "Special:" not in href: article_url = "https://harrypotter.fandom.com" + href break if not article_url: return "No results found for your query." # Fetch the article page. article_response = requests.get(article_url, headers=headers) if article_response.status_code != 200: return f"Error: Received status code {article_response.status_code} from the article page." article_soup = BeautifulSoup(article_response.text, 'html.parser') # Extract the first meaningful paragraph. paragraphs = article_soup.find_all("p") for p in paragraphs: text = p.get_text().strip() if len(text) > 50: # A simple threshold to ensure the paragraph is informative. return text return "Couldn't extract detailed lore from the article." except Exception as e: return f"An error occurred: {str(e)}" # Initialize the SmolAgent model model = HfApiModel(model_id="HuggingFaceTB/SmolLM2-360M", token=hf_token) # Create the agent agent = CodeAgent(tools=[search_harry_potter_lore], model=model) def apply_custom_styles(): st.markdown( """ """, unsafe_allow_html=True ) def main(): apply_custom_styles() # Initialize session state variables if not set if "state_reset" not in st.session_state: st.session_state["state_reset"] = True if st.session_state["state_reset"]: st.session_state["user_input"] = "" st.session_state["response"] = None st.session_state["waiting_for_input"] = True st.session_state["state_reset"] = False def process_input(): """Fetch Tom Riddle's response based on user input.""" user_input = st.session_state["user_input"] if user_input.strip(): try: response = agent.run( f"You are Tom Riddle, a cunning and enigmatic character from Harry Potter (you're not evil yet). Respond concisely and pragmatically but please don't be evil and remain true to your role in the series: {user_input}" ) st.session_state["response"] = response st.session_state["waiting_for_input"] = False except Exception as e: st.error(f"An error occurred: {e}") # Show input area or response based on state if st.session_state["waiting_for_input"]: st.text_area( "", placeholder="Write your thoughts here...", key="user_input", on_change=process_input, ) elif st.session_state["response"]: st.markdown( f"