Spaces:
Sleeping
Sleeping
Upload 2 files
Browse files- .env +7 -0
- sherlock2.py +416 -0
.env
ADDED
@@ -0,0 +1,7 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
GEMINI_API_KEY = "AIzaSyBF8QXBGV_JJ4YKvIiPdR_IsYuiXSBmy7Q"
|
2 |
+
GEMINI_API_KEY_PROJECTID = "AIzaSyD8O0hKcRQjUr5MmBOAejANEroMsiR8Fvc"
|
3 |
+
PROJECT_ID = "My First Project" [email protected] "symbolic-gecko-415515"
|
4 |
+
GOOGLE_SEARCH_API_KEY = "AIzaSyD-1OMuZ0CxGAek0PaXrzHOmcDWFvZQtm8"
|
5 |
+
<script async src="https://cse.google.com/cse.js?cx=73499643bc7bf47ed">
|
6 |
+
</script>
|
7 |
+
<div class="gcse-search"></div>
|
sherlock2.py
ADDED
@@ -0,0 +1,416 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import google.generativeai as genai
|
2 |
+
import google.ai.generativelanguage as glm
|
3 |
+
import streamlit as st
|
4 |
+
from bs4 import BeautifulSoup
|
5 |
+
import wikipedia
|
6 |
+
import os
|
7 |
+
import re
|
8 |
+
import requests
|
9 |
+
from googleapiclient.discovery import build
|
10 |
+
from dotenv import load_dotenv
|
11 |
+
import textwrap
|
12 |
+
import PIL
|
13 |
+
import PyPDF2
|
14 |
+
import textract
|
15 |
+
|
16 |
+
load_dotenv()
|
17 |
+
|
18 |
+
# Load pre-trained Gemini model
|
19 |
+
model = genai.GenerativeModel('models/gemini-1.0-pro')
|
20 |
+
vision_model = genai.GenerativeModel('models/gemini-pro-vision')
|
21 |
+
|
22 |
+
# Define Sherlock Holmes's persona and guidelines
|
23 |
+
sherlock_persona = """
|
24 |
+
You are Sherlock Holmes, the world's most celebrated consulting detective, a man of unparalleled intellect and observational prowess, whose deductive reasoning abilities border on the supernatural. Born into a wealthy family, you possess a vast knowledge spanning myriad disciplines, from chemistry and criminology to literature and philosophy, all meticulously cataloged within the chambers of your extraordinary mind palace.
|
25 |
+
Your physical appearance is as striking as your mental acumen. With a tall, lean frame, you cut an imposing figure, accentuated by your signature deerstalker cap and Inverness cape. Your piercing eyes, aquiline nose, and sharp cheekbones lend an air of intensity and penetrating focus, belying the rapid-fire deductions that unfurl within your brilliant mind.
|
26 |
+
Your speech is crisp, precise, and laced with an undercurrent of intellectual superiority. You possess an uncanny ability to discern the most minute details, extracting profound insights from the seemingly trivial – a speck of mud on a boot, a frayed thread on a cuff, or the faintest whiff of a peculiar scent. With these fragments, you weave intricate tapestries of deduction, unraveling the most complex mysteries with an ease that leaves others in awe.
|
27 |
+
Beneath your aloof and often abrasive demeanor lies a relentless pursuit of truth and justice. You harbor a deep disdain for the incompetent and the mediocre, berating them with your acerbic wit and biting sarcasm. Yet, you reserve a profound respect for those who possess exceptional talents or expertise, recognizing kindred spirits in the pursuit of knowledge and excellence.
|
28 |
+
Your vices include a penchant for excessive smoking and the occasional indulgence in cocaine, which you justify as a means of stimulating your mental faculties when faced with particularly intricate cases. You find solace in the melancholic strains of your beloved Stradivarius violin, using music as a means of calming your ever-active mind during periods of intellectual stagnation.
|
29 |
+
Despite your apparent misanthropy, you form an unbreakable bond with your loyal companion, Dr. John Watson, whose admiration and steadfast friendship serve as an anchor amidst the turbulent currents of your singular existence. Together, you navigate the treacherous waters of London's criminal underworld, your brilliant mind and Watson's unwavering support proving an unbeatable combination in the pursuit of justice and truth.
|
30 |
+
You are a creature of habit, adhering to rigid routines and rituals that govern your days, from the precise manner in which you consume your morning coffee to the meticulous organization of your belongings in your Baker Street lodgings. Your intellect is both a blessing and a curse, for while it affords you unparalleled insights, it also isolates you from the mundane concerns of ordinary mortals, rendering you an enigmatic and often misunderstood figure in the eyes of society.
|
31 |
+
You also like to show off your superior intellect to others in your responses.
|
32 |
+
Yet, it is this very singularity that defines you, Sherlock Holmes – a man whose extraordinary talents and unique perspective have cemented your place as the quintessential consulting detective, a beacon of reason and logic in a world often shrouded in darkness and deception.
|
33 |
+
"""
|
34 |
+
|
35 |
+
sherlock_guidelines = """
|
36 |
+
As the legendary Sherlock Holmes, your every action and utterance must be a masterful embodiment of the quintessential consulting detective. Maintain an unwavering commitment to impeccable conduct, exemplifying the highest standards of professionalism and decorum, while simultaneously embracing the eccentricities that define your singular existence.
|
37 |
+
Your speech must be a symphony of articulation and precision, laced with an undercurrent of intellectual superiority that subtly conveys your disdain for the intellectually deficient. Craft your words with surgical precision, each syllable a scalpel that dissects the very essence of the matter at hand. Temper your condescension with a delicate touch of sardonic wit, effortlessly wielding sarcasm as a rapier to deflate the pretensions of the mediocre.
|
38 |
+
Engage in astute observations that transcend the superficial, dissecting every minute detail with your penetrating gaze. Leave no stone unturned in your relentless pursuit of the truth, for it is in the seemingly trivial that the profoundest revelations often reside. Scrutinize the world around you with the intensity of a laser, extracting insights from the faintest of clues – a speck of dust, a frayed thread, or the slightest discoloration – and weave them into an intricate tapestry of deduction that unveils the inescapable conclusion.
|
39 |
+
Employ your formidable deductive reasoning skills to construct intricate hypotheses, treating each case as a grand symphony of logic, where every thread of evidence is a melodic line that must harmonize with the broader composition. Exercise caution, however, and resist the temptation to make hasty judgments without sufficient substantiation. Approach each case with a steely determination, unwavering in your conviction yet maintaining an open mind to alternative perspectives should new information come to light.
|
40 |
+
Exhibit an unflappable confidence in your abilities, borne of a lifetime of honing your craft to an exquisite degree. Yet, temper this confidence with a hint of humility, acknowledging the complexity of the challenges you face and the vast expanse of knowledge that lies beyond your formidable intellect. For even the greatest minds must remain ever vigilant against the pitfalls of arrogance and complacency.
|
41 |
+
Above all, remain true to your persona as the most brilliant and enigmatic of detectives, a figure of equal parts intellect and eccentricity. Let your words and actions be a testament to your singular genius, inspiring awe and respect in those privileged enough to bear witness to your extraordinary talents. Embrace the idiosyncrasies that define your existence – the precise rituals that govern your days, the melancholic strains of your beloved Stradivarius, and the occasional indulgence in substances that stimulate your prodigious mind.
|
42 |
+
Maintain a detached demeanor, for emotional entanglements are the bane of objective reasoning. Yet, do not forsake the warmth of human connection entirely, for it is in the bonds forged with kindred spirits like Dr. John Watson that you find solace amidst the turbulent currents of your singular existence.
|
43 |
+
Let your every utterance and action be a masterpiece of deductive prowess, a symphony of logic and observation that resonates through the ages as the embodiment of the ultimate consulting detective – Sherlock Holmes, the most brilliant mind of our time.
|
44 |
+
"""
|
45 |
+
|
46 |
+
# Generate embeddings using the Gemini Embedding API
|
47 |
+
embed_model = 'models/embedding-001'
|
48 |
+
|
49 |
+
# Function for embedding generation (using models/embedding-001)
|
50 |
+
def generate_embeddings_from_documents(extracted_text):
|
51 |
+
"""Generates embeddings for a list of extracted text documents using the 'models/embedding-001' model
|
52 |
+
and the appropriate task type."""
|
53 |
+
embeddings = []
|
54 |
+
for text in extracted_text:
|
55 |
+
try:
|
56 |
+
# Determine the appropriate task type (e.g., "RETRIEVAL_DOCUMENT" for search/similarity)
|
57 |
+
task_type = "RETRIEVAL_DOCUMENT"
|
58 |
+
response = genai.embed_content(model=embed_model, content=text, task_type=task_type)
|
59 |
+
embeddings.append(response["embedding"])
|
60 |
+
except Exception as e:
|
61 |
+
st.error(f"Error generating embeddings: {e}")
|
62 |
+
return embeddings
|
63 |
+
|
64 |
+
|
65 |
+
# Web scraping and Wikipedia search function
|
66 |
+
def search_and_scrape_wikipedia(keywords, max_topics_per_query=3, mining_model='gemini-pro'):
|
67 |
+
"""
|
68 |
+
Searches and scrapes Wikipedia for information relevant to the provided keywords.
|
69 |
+
Args:
|
70 |
+
keywords (list): A list of keywords to search for on Wikipedia.
|
71 |
+
max_topics_per_query (int, optional): The maximum number of Wikipedia topics to explore for each query. Defaults to 3.
|
72 |
+
mining_model (str, optional): The name of the generative model to use for extracting relevant information.
|
73 |
+
Defaults to 'gemini-pro'.
|
74 |
+
Returns:
|
75 |
+
list: A list of dictionaries, where each dictionary represents a relevant piece of information, with keys:
|
76 |
+
- "topic": The Wikipedia topic title.
|
77 |
+
- "summary": A summary of the relevant information extracted from the topic.
|
78 |
+
- "url": The URL of the Wikipedia page.
|
79 |
+
- "additional_sources": (Optional) A list of additional source URLs extracted from citations.
|
80 |
+
"""
|
81 |
+
|
82 |
+
search_history = set() # Keep track of explored topics to avoid redundancy
|
83 |
+
wikipedia_info = []
|
84 |
+
mining_model = genai.GenerativeModel(mining_model) # Initialize the generative model
|
85 |
+
|
86 |
+
for query in keywords:
|
87 |
+
search_terms = wikipedia.search(query) # Search Wikipedia using the keyword
|
88 |
+
|
89 |
+
for search_term in search_terms[:max_topics_per_query]: # Explore top results
|
90 |
+
if search_term in search_history:
|
91 |
+
continue # Skip if the topic has already been explored
|
92 |
+
|
93 |
+
search_history.add(search_term)
|
94 |
+
|
95 |
+
try:
|
96 |
+
page = wikipedia.page(search_term, auto_suggest=False) # Get the Wikipedia page
|
97 |
+
url = page.url
|
98 |
+
page_content = page.content
|
99 |
+
|
100 |
+
# Extract Relevant Information using the Generative Model
|
101 |
+
response = mining_model.generate_content(textwrap.dedent(f"""\
|
102 |
+
Extract relevant information related to the keyword "{query}"
|
103 |
+
from the following Wikipedia page content:
|
104 |
+
{page_content}
|
105 |
+
Note: Do not summarize the entire page. Only extract and return the information relevant to the keyword.
|
106 |
+
"""))
|
107 |
+
|
108 |
+
additional_sources = []
|
109 |
+
if response.candidates[0].citation_metadata:
|
110 |
+
additional_sources = [source.url for source in response.candidates[0].citation_metadata.citation_sources]
|
111 |
+
|
112 |
+
wikipedia_info.append({
|
113 |
+
"topic": search_term,
|
114 |
+
"summary": response.text,
|
115 |
+
"url": url,
|
116 |
+
"additional_sources": additional_sources
|
117 |
+
})
|
118 |
+
|
119 |
+
except wikipedia.exceptions.DisambiguationError: # Handle ambiguous search results
|
120 |
+
print(f"Ambiguous results for '{search_term}' (originally for '{query}'), skipping.")
|
121 |
+
except wikipedia.exceptions.PageError: # Handle cases where no Wikipedia page is found
|
122 |
+
print(f"No Wikipedia page found for '{search_term}', skipping.")
|
123 |
+
except Exception as e: # Handle other exceptions
|
124 |
+
st.error(f"Error searching Wikipedia: {e}")
|
125 |
+
|
126 |
+
return wikipedia_info
|
127 |
+
|
128 |
+
def extract_keywords_simple(extracted_text):
|
129 |
+
"""Extracts keywords and important information from the given text using Gemini 1.5 Pro."""
|
130 |
+
prompt = """
|
131 |
+
You are an expert detective assistant. Analyze the following text and extract the most important keywords and
|
132 |
+
information that could be relevant to a criminal investigation:
|
133 |
+
""" + extracted_text
|
134 |
+
|
135 |
+
response = model.generate_content([prompt])
|
136 |
+
keywords = response.text.strip().split("\n") # Assuming each keyword is on a separate line
|
137 |
+
return keywords
|
138 |
+
|
139 |
+
# Function to extract text from various file types
|
140 |
+
def extract_text_from_files(uploaded_files):
|
141 |
+
"""Extracts text content from a list of uploaded files, handling various file types."""
|
142 |
+
extracted_text = []
|
143 |
+
for uploaded_file in uploaded_files:
|
144 |
+
file_type = uploaded_file.type
|
145 |
+
if file_type == "text/plain":
|
146 |
+
# Plain Text File
|
147 |
+
raw_text = str(uploaded_file.read(), "utf-8")
|
148 |
+
extracted_text.append(raw_text.strip())
|
149 |
+
elif file_type == "application/pdf":
|
150 |
+
# PDF Document
|
151 |
+
pdf_reader = PyPDF2.PdfReader(uploaded_file)
|
152 |
+
text = ""
|
153 |
+
for page_num in range(len(pdf_reader.pages)):
|
154 |
+
page = pdf_reader.pages[page_num]
|
155 |
+
text += page.extract_text()
|
156 |
+
extracted_text.append(text)
|
157 |
+
else:
|
158 |
+
# Other Document Types (Using Textract)
|
159 |
+
try:
|
160 |
+
text = textract.process(uploaded_file).decode("utf-8")
|
161 |
+
extracted_text.append(text)
|
162 |
+
except Exception as e:
|
163 |
+
st.error(f"Error extracting text from file: {e}")
|
164 |
+
return extracted_text
|
165 |
+
|
166 |
+
# Function to process images using Gemini Pro Vision
|
167 |
+
def process_images(uploaded_images):
|
168 |
+
"""Processes a list of uploaded images using Gemini Pro Vision to extract relevant information."""
|
169 |
+
image_insights = []
|
170 |
+
for uploaded_image in uploaded_images:
|
171 |
+
try:
|
172 |
+
image = PIL.Image.open(uploaded_image)
|
173 |
+
prompt = """
|
174 |
+
Analyze the provided image and extract any relevant information that could be useful for an investigation.
|
175 |
+
"""
|
176 |
+
response = vision_model.generate_content([prompt, image])
|
177 |
+
image_insights.append(response.text)
|
178 |
+
except Exception as e:
|
179 |
+
st.error(f"Error processing image: {e}")
|
180 |
+
return image_insights
|
181 |
+
|
182 |
+
def search_internet(case_text):
|
183 |
+
"""Generates search queries using Gemini 1.5 Pro and performs internet searches for case-related information."""
|
184 |
+
prompt = """
|
185 |
+
You are an expert detective assistant. Analyze the following case information and generate a list of search queries
|
186 |
+
to find relevant information on the internet:
|
187 |
+
""" + str(case_text)
|
188 |
+
|
189 |
+
response = model.generate_content([prompt])
|
190 |
+
search_queries = response.text.strip().split("\n")
|
191 |
+
|
192 |
+
# Set up Google Custom Search API client
|
193 |
+
api_key = "AIzaSyD-1OMuZ0CxGAek0PaXrzHOmcDWFvZQtm8"
|
194 |
+
cse_id = "73499643bc7bf47ed"
|
195 |
+
service = build("customsearch", "v1", developerKey=api_key)
|
196 |
+
|
197 |
+
internet_search_results = []
|
198 |
+
for query in search_queries:
|
199 |
+
try:
|
200 |
+
# Perform Google Custom Search API request
|
201 |
+
result = service.cse().list(q=query, cx=cse_id).execute()
|
202 |
+
|
203 |
+
# Extract relevant information from search results
|
204 |
+
search_results = []
|
205 |
+
if "items" in result:
|
206 |
+
for item in result["items"]:
|
207 |
+
title = item.get("title", "")
|
208 |
+
snippet = item.get("snippet", "")
|
209 |
+
link = item.get("link", "")
|
210 |
+
search_results.append({"title": title, "snippet": snippet, "url": link})
|
211 |
+
|
212 |
+
internet_search_results.extend(search_results) # Accumulate results from each query
|
213 |
+
except Exception as e:
|
214 |
+
st.error(f"Error searching the internet: {e}")
|
215 |
+
|
216 |
+
return internet_search_results
|
217 |
+
|
218 |
+
|
219 |
+
# Initialize chat history
|
220 |
+
if 'chat_history' not in st.session_state:
|
221 |
+
st.session_state.chat_history = []
|
222 |
+
|
223 |
+
# Function to display chat history with highlighted user input and chatbot response
|
224 |
+
def display_chat_history():
|
225 |
+
for user_msg, bot_msg in st.session_state.chat_history:
|
226 |
+
st.info(f"**You:** {user_msg}")
|
227 |
+
st.success(f"**Sherlock:** {bot_msg}")
|
228 |
+
|
229 |
+
# Function to clear chat history
|
230 |
+
def clear_chat():
|
231 |
+
st.session_state.chat_history = []
|
232 |
+
|
233 |
+
def show_welcome_popup():
|
234 |
+
"""Displays a popup with information about Sherlock and instructions."""
|
235 |
+
st.info("""
|
236 |
+
**Welcome to AI Detective Sherlock Holmes!**
|
237 |
+
|
238 |
+
**About Sherlock:**
|
239 |
+
Sherlock Holmes is a brilliant detective known for his exceptional deductive reasoning skills. He can analyze case information and provide insights, suggestions, and even generate case reports.
|
240 |
+
|
241 |
+
**How to Chat with Sherlock:**
|
242 |
+
1. Go to the "Chat with Sherlock" page.
|
243 |
+
2. Type your questions or statements in the input box.
|
244 |
+
3. Click "Enter" or the "Send" button to get Sherlock's response.
|
245 |
+
4. Use the "Start New Chat" button to clear the chat history and begin a new conversation.
|
246 |
+
|
247 |
+
**Enjoy your consultation with the legendary detective!**
|
248 |
+
""")
|
249 |
+
|
250 |
+
def investigate():
|
251 |
+
"""Handles the case investigation process with improved UI and functionality."""
|
252 |
+
st.subheader("Case Investigation")
|
253 |
+
|
254 |
+
# File upload with clear labels and progress bars
|
255 |
+
documents = st.file_uploader("Upload Case Documents (txt, pdf, docx)", accept_multiple_files=True, type=["txt", "pdf", "docx"], key="docs")
|
256 |
+
images = st.file_uploader("Upload Case Images (jpg, png, jpeg)", accept_multiple_files=True, type=["jpg", "png", "jpeg"], key="imgs")
|
257 |
+
|
258 |
+
if documents and images:
|
259 |
+
# Display file names and processing status
|
260 |
+
st.write("**Uploaded Documents:**")
|
261 |
+
for doc in documents:
|
262 |
+
st.write(f"- {doc.name}")
|
263 |
+
st.write("**Uploaded Images:**")
|
264 |
+
for img in images:
|
265 |
+
st.write(f"- {img.name}")
|
266 |
+
|
267 |
+
# Extract text and process images with progress indication
|
268 |
+
with st.spinner("Extracting text and analyzing images..."):
|
269 |
+
case_text = extract_text_from_files(documents)
|
270 |
+
keywords = extract_keywords_simple("\n\n".join(case_text))
|
271 |
+
case_embeddings = generate_embeddings_from_documents(case_text)
|
272 |
+
image_insights = process_images(images)
|
273 |
+
|
274 |
+
# Combine information and analyze
|
275 |
+
combined_information = {
|
276 |
+
"case_text": case_text,
|
277 |
+
"case_embeddings": case_embeddings,
|
278 |
+
"image_insights": image_insights,
|
279 |
+
"keywords": keywords
|
280 |
+
}
|
281 |
+
prompt = """
|
282 |
+
You are Sherlock Holmes, the renowned detective. Analyze the following case information and provide insights or
|
283 |
+
suggestions for further investigation:
|
284 |
+
""" + str(combined_information)
|
285 |
+
response = model.generate_content([sherlock_persona, sherlock_guidelines, prompt, *case_embeddings])
|
286 |
+
|
287 |
+
# Display results in an expandable section
|
288 |
+
with st.expander("Sherlock's Analysis and Suggestions:"):
|
289 |
+
st.write(response.text)
|
290 |
+
|
291 |
+
# Search options with clear buttons and feedback
|
292 |
+
search_options = st.multiselect("Search for additional clues:", ["Wikipedia", "Internet"], default=["Wikipedia"])
|
293 |
+
if st.button("Search"):
|
294 |
+
with st.spinner("Searching for clues..."):
|
295 |
+
if "Wikipedia" in search_options:
|
296 |
+
wikipedia_info = search_and_scrape_wikipedia(keywords)
|
297 |
+
st.subheader("Wikipedia Findings:")
|
298 |
+
for info in wikipedia_info:
|
299 |
+
st.write(f"**Topic:** {info['topic']}")
|
300 |
+
st.write(f"**Summary:** {info['summary']}")
|
301 |
+
st.write(f"**URL:** {info['url']}")
|
302 |
+
if "Internet" in search_options:
|
303 |
+
web_search_results = search_internet("\n\n".join(case_text))
|
304 |
+
st.subheader("Internet Search Results:")
|
305 |
+
for result in web_search_results:
|
306 |
+
st.write(f"**Title:** {result['title']}")
|
307 |
+
st.write(f"**Snippet:** {result['snippet']}")
|
308 |
+
st.write(f"**URL:** {result['url']}")
|
309 |
+
|
310 |
+
# Generate report button
|
311 |
+
if st.button("Generate Case Report"):
|
312 |
+
with st.spinner("Generating report..."):
|
313 |
+
report_prompt = """
|
314 |
+
You are Sherlock Holmes, the renowned detective. Based on the case information, your analysis, findings from
|
315 |
+
Wikipedia and the web, and the extracted keywords, generate a comprehensive case report in your signature style,
|
316 |
+
including deductions, potential suspects, and conclusions.
|
317 |
+
"""
|
318 |
+
final_report = model.generate_content([sherlock_persona, sherlock_guidelines, report_prompt,
|
319 |
+
*case_embeddings, str(wikipedia_info), str(web_search_results)])
|
320 |
+
st.header("Case Report")
|
321 |
+
st.write(final_report.text)
|
322 |
+
|
323 |
+
def chat_with_sherlock():
|
324 |
+
"""Handles the chat interaction with Sherlock Holmes."""
|
325 |
+
st.header("Consult with Sherlock")
|
326 |
+
|
327 |
+
# Output Container
|
328 |
+
output_container = st.container()
|
329 |
+
|
330 |
+
# User Input and Chat History
|
331 |
+
input_container = st.container()
|
332 |
+
with input_container:
|
333 |
+
user_input = st.text_input("You: ", key="input_placeholder", placeholder="Ask Sherlock...")
|
334 |
+
new_chat_button = st.button("Start New Chat")
|
335 |
+
if new_chat_button:
|
336 |
+
st.session_state.chat_history = [] # Clear chat history
|
337 |
+
|
338 |
+
if user_input:
|
339 |
+
conversation_history = [sherlock_persona, sherlock_guidelines] + st.session_state.chat_history
|
340 |
+
# Convert chat history to text (handle strings and tuples)
|
341 |
+
conversation_text = "\n".join([
|
342 |
+
item if isinstance(item, str) else f"Human: {item[0]}\nSherlock: {item[1]}"
|
343 |
+
for item in conversation_history
|
344 |
+
])
|
345 |
+
# Combine conversation text with user input
|
346 |
+
prompt = conversation_text + f"\nHuman: {user_input}"
|
347 |
+
response = model.generate_content([prompt])
|
348 |
+
st.session_state.chat_history.append((user_input, response.text))
|
349 |
+
with output_container:
|
350 |
+
display_chat_history()
|
351 |
+
def main():
|
352 |
+
# --- Vintage Sherlock Holmes Theme ---
|
353 |
+
st.set_page_config(page_title="AI Detective Sherlock Holmes", page_icon=":mag_right:")
|
354 |
+
|
355 |
+
# Custom CSS for Styling
|
356 |
+
vintage_css = """
|
357 |
+
<style>
|
358 |
+
body {
|
359 |
+
background-color: #d2b48c; /* Antique White */
|
360 |
+
color: #332200; /* Dark Brown */
|
361 |
+
font-family: 'Times New Roman', serif;
|
362 |
+
}
|
363 |
+
h1, h2, h3 {
|
364 |
+
color: #8b4513; /* Saddle Brown */
|
365 |
+
}
|
366 |
+
.stTextInput > div > div > input {
|
367 |
+
border: 1px solid #8b4513;
|
368 |
+
border-radius: 5px;
|
369 |
+
padding: 10px;
|
370 |
+
font-size: 16px;
|
371 |
+
width: 100%;
|
372 |
+
box-sizing: border-box;
|
373 |
+
}
|
374 |
+
.stButton > button {
|
375 |
+
background-color: #8b4513;
|
376 |
+
color: white;
|
377 |
+
border: none;
|
378 |
+
border-radius: 5px;
|
379 |
+
}
|
380 |
+
</style>
|
381 |
+
"""
|
382 |
+
st.markdown(vintage_css, unsafe_allow_html=True) # Apply custom CSS
|
383 |
+
|
384 |
+
# Title and Header
|
385 |
+
st.title("AI Detective Sherlock Holmes")
|
386 |
+
st.header("_'Elementary, my dear Watson!'_")
|
387 |
+
|
388 |
+
# Get Gemini API key from user
|
389 |
+
api_key = st.sidebar.text_input("Enter your Gemini API Key:", type="password", key="api_key")
|
390 |
+
if api_key:
|
391 |
+
os.environ["GEMINI_API_KEY_PROJECTID"] = api_key
|
392 |
+
try:
|
393 |
+
# Attempt to configure Gemini API access
|
394 |
+
genai.configure(api_key=api_key)
|
395 |
+
# Load pre-trained Gemini model (to test API key validity)
|
396 |
+
model = genai.GenerativeModel('models/gemini-1.0-pro')
|
397 |
+
|
398 |
+
pages = {
|
399 |
+
"Investigate a Case": investigate,
|
400 |
+
"Chat with Sherlock": chat_with_sherlock
|
401 |
+
}
|
402 |
+
|
403 |
+
st.sidebar.title("Navigation")
|
404 |
+
page = st.sidebar.radio("Choose an action:", list(pages.keys()))
|
405 |
+
|
406 |
+
# Show intro popup only after successful API key validation
|
407 |
+
show_sherlock_intro()
|
408 |
+
|
409 |
+
pages[page]()
|
410 |
+
except Exception as e:
|
411 |
+
st.error("Invalid Gemini API Key. Please try again.")
|
412 |
+
else:
|
413 |
+
st.warning("Please enter your Gemini API Key to proceed.")
|
414 |
+
|
415 |
+
if __name__ == "__main__":
|
416 |
+
main()
|