JACK / app.py
hashirlodhi's picture
Upload 2 files
011757f verified
Raw
History Blame Contribute Delete
8.21 kB
import os
from dotenv import load_dotenv
import gradio as gr
from groq import Groq
from exa_py import Exa
load_dotenv()
groq_client = Groq(api_key=os.getenv("GROQ_API_KEY"))
groq_model = "llama-3.3-70b-versatile"
exa_client = Exa(api_key=os.getenv("EXA_API"))
def generate_verification_query(text, speaker):
prompt = f"""Someone said: "{text}"
The speaker is: {speaker}
Generate a specific, concise search query that would verify if this statement is factually true or false. The query should be specific enough to fact-check this exact claim. Return ONLY the search query, nothing else."""
try:
response = groq_client.chat.completions.create(
model=groq_model,
messages=[{"role": "user", "content": prompt}],
temperature=0.1,
max_tokens=100
)
return response.choices[0].message.content.strip()
except Exception as e:
return f"Error generating query: {e}"
def search_with_exa(query):
try:
response = exa_client.search(
query=query,
num_results=10,
type="neural"
)
sources = []
for result in response.results:
sources.append({
"title": result.title or "No title",
"url": result.url,
"text": result.text[:500] if result.text else ""
})
return sources
except Exception as e:
return f"Error searching: {e}"
def agent_claim_made(claim, speaker, sources):
sources_text = "\n\n".join([
f"Source {i+1}: {s['title']}\nURL: {s['url']}\nContent: {s['text']}"
for i, s in enumerate(sources)
])
source_refs = "\n".join([f"Source {i+1}: [{s['title']}]({s['url']})" for i, s in enumerate(sources)])
prompt = f"""Based on the verification sources below, answer ONLY this question:
CLAIM: "{claim}"
SPEAKER: {speaker}
SOURCES:
{sources_text}
## 1. Was this claim made by the sayer?
[Answer based on sources - did this person actually make this statement? Provide a clear, evidence-based answer with specific citations.
IMPORTANT: Inline cite sources using markdown links like this: "According to [Source 1](URL), ..." or "As stated in [Source 2](URL), ..."
Use the exact source titles and URLs from this reference list:
{source_refs}]"""
try:
response = groq_client.chat.completions.create(
model=groq_model,
messages=[{"role": "user", "content": prompt}],
temperature=0.2,
max_tokens=800
)
return response.choices[0].message.content.strip()
except Exception as e:
return f"Error: {e}"
def agent_action_done(claim, speaker, sources):
sources_text = "\n\n".join([
f"Source {i+1}: {s['title']}\nURL: {s['url']}\nContent: {s['text']}"
for i, s in enumerate(sources)
])
source_refs = "\n".join([f"Source {i+1}: [{s['title']}]({s['url']})" for i, s in enumerate(sources)])
prompt = f"""Based on the verification sources below, answer ONLY this question:
CLAIM: "{claim}"
SPEAKER: {speaker}
SOURCES:
{sources_text}
## 2. Was this action/event done by the sayer?
[Answer based on sources - did the person actually do what they claimed? Provide a clear, evidence-based answer with specific citations.
IMPORTANT: Inline cite sources using markdown links like this: "According to [Source 1](URL), ..." or "As stated in [Source 2](URL), ..."
Use the exact source titles and URLs from this reference list:
{source_refs}]"""
try:
response = groq_client.chat.completions.create(
model=groq_model,
messages=[{"role": "user", "content": prompt}],
temperature=0.2,
max_tokens=800
)
return response.choices[0].message.content.strip()
except Exception as e:
return f"Error: {e}"
def agent_consequences(claim, speaker, sources):
sources_text = "\n\n".join([
f"Source {i+1}: {s['title']}\nURL: {s['url']}\nContent: {s['text']}"
for i, s in enumerate(sources)
])
source_refs = "\n".join([f"Source {i+1}: [{s['title']}]({s['url']})" for i, s in enumerate(sources)])
prompt = f"""Based on the verification sources below, answer ONLY this question:
CLAIM: "{claim}"
SPEAKER: {speaker}
SOURCES:
{sources_text}
## 3. What were the consequences of this act/statement?
[Detail the consequences, outcomes, or impact based on sources. Provide a clear, evidence-based answer with specific citations.
IMPORTANT: Inline cite sources using markdown links like this: "According to [Source 1](URL), ..." or "As stated in [Source 2](URL), ..."
Use the exact source titles and URLs from this reference list:
{source_refs}]"""
try:
response = groq_client.chat.completions.create(
model=groq_model,
messages=[{"role": "user", "content": prompt}],
temperature=0.2,
max_tokens=800
)
return response.choices[0].message.content.strip()
except Exception as e:
return f"Error: {e}"
def agent_sources(sources):
prompt = f"""Format these sources as clickable markdown links, one per line:
SOURCES:
{chr(10).join([f"{i+1}. {s['title']} - {s['url']}" for i, s in enumerate(sources)])}
Return ONLY the markdown list, nothing else."""
try:
response = groq_client.chat.completions.create(
model=groq_model,
messages=[{"role": "user", "content": prompt}],
temperature=0.1,
max_tokens=500
)
return response.choices[0].message.content.strip()
except Exception as e:
return "\n".join([f"- [{s['title']}]({s['url']})" for s in sources])
def verify_claim(text, speaker, progress=gr.Progress()):
if not text or not speaker:
return "Please provide both claim and speaker name."
progress(0.1, desc="Generating search query...")
query = generate_verification_query(text, speaker)
if query.startswith("Error"):
return query
progress(0.3, desc="Searching Exa API...")
sources = search_with_exa(query)
if isinstance(sources, str) and sources.startswith("Error"):
return sources
if not sources:
return "No sources found for verification."
progress(0.5, desc="Agent 1: Verifying claim attribution...")
part1 = agent_claim_made(text, speaker, sources)
progress(0.65, desc="Agent 2: Verifying action/event...")
part2 = agent_action_done(text, speaker, sources)
progress(0.8, desc="Agent 3: Analyzing consequences...")
part3 = agent_consequences(text, speaker, sources)
progress(0.9, desc="Agent 4: Formatting sources...")
part4 = agent_sources(sources)
progress(1.0, desc="Complete!")
return f"""## 1. Was this claim made by the sayer?
{part1}
## 2. Was this action/event done by the sayer?
{part2}
## 3. What were the consequences of this act/statement?
{part3}
## Sources
{part4}"""
with gr.Blocks() as demo:
gr.Markdown("## Fact Verification")
gr.Markdown("Enter a claim and who said it, then click Verify. Four specialized agents will analyze the evidence.")
with gr.Row():
selected_text = gr.Textbox(label="Claim", placeholder="Enter the claim to fact-check...")
speaker = gr.Textbox(label="Who said this?", placeholder="e.g., Jeff Bezos, Elon Musk, etc.")
verify_btn = gr.Button("Verify Claim", variant="primary", size="lg")
status_msg = gr.Markdown(value="", visible=False)
verification_output = gr.Markdown(label="Verification Result")
def start_verification(text, speaker):
# Show status message and make it visible
return gr.update(value="🤖 **Agents are handling your research — just sit tight!**", visible=True)
verify_btn.click(
fn=start_verification,
inputs=[selected_text, speaker],
outputs=status_msg
).then(
verify_claim,
inputs=[selected_text, speaker],
outputs=verification_output,
show_progress="full"
).then(
lambda: gr.update(visible=False),
outputs=status_msg
)
if __name__ == "__main__":
demo.launch()