Spaces:
Build error
Build error
| 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() |