import gradio as gr import pandas as pd import httpx import re, json, asyncio from openai import OpenAI from itertools import cycle import aiohttp import asyncio import requests import csv import os # 🔑 Hardcoded credentials (you provided) OPENAI_API_KEY = "OAPI1" DEEPSEEK_API_KEY = "DAPI" GOOGLE_API_KEY = "API1" GOOGLE_CSE_ID = "CX1" OPENAI_MODEL = "gpt-4o-mini" DEEPSEEK_MODEL = "deepseek-chat" # ---------------- Helper functions ---------------- async def google_cse(query, num=4): url = "https://www.googleapis.com/customsearch/v1" params = {"q": query, "cx": GOOGLE_CSE_ID, "key": GOOGLE_API_KEY, "num": num} async with httpx.AsyncClient(timeout=30.0) as client: r = await client.get(url, params=params) r.raise_for_status() items = r.json().get("items", []) return [{"title": it.get("title"), "link": it.get("link"), "snippet": it.get("snippet")} for it in items] async def call_openai(messages): url = "https://api.openai.com/v1/chat/completions" headers = {"Authorization": f"Bearer {OPENAI_API_KEY}"} payload = {"model": OPENAI_MODEL, "messages": messages, "temperature": 0, "max_tokens": 800} async with httpx.AsyncClient(timeout=60.0) as client: r = await client.post(url, headers=headers, json=payload) r.raise_for_status() return r.json()["choices"][0]["message"]["content"] async def call_deepseek(messages): url = "https://api.deepseek.com/v1/chat/completions" headers = {"Authorization": f"Bearer {DEEPSEEK_API_KEY}"} payload = {"model": DEEPSEEK_MODEL, "messages": messages, "temperature": 0, "max_tokens": 800} async with httpx.AsyncClient(timeout=60.0) as client: r = await client.post(url, headers=headers, json=payload) r.raise_for_status() return r.json()["choices"][0]["message"]["content"] def split_claims(text): parts = re.split(r"[.;\n]", str(text)) return [p.strip() for p in parts if len(p.strip()) > 5][:10] async def verify_claim(claim): results = await google_cse(claim, num=3) sources = "\n".join([f"- {r['title']} ({r['link']}): {r['snippet']}" for r in results]) user = f"CLAIM: {claim}\n\nSOURCES:\n{sources}" messages = [ {"role": "system", "content": "You are a fact-checker. Return JSON {status, reason, citations[]}"}, {"role": "user", "content": user} ] oai, dsk = await asyncio.gather(call_openai(messages), call_deepseek(messages)) return {"claim": claim, "openai": oai, "deepseek": dsk, "sources": results} async def process_csv(file): df = pd.read_csv(file) if "Requirement" not in df.columns and "Requirements" not in df.columns: raise gr.Error("CSV must have a 'Requirement' or 'Requirements' column") col = "Requirement" if "Requirement" in df.columns else "Requirements" all_results = [] for idx, row in df.iterrows(): text = str(row[col]) claims = split_claims(text) claim_results = [await verify_claim(c) for c in claims] all_results.append({"ID": row.get("ID", idx), "results": claim_results}) # Make summary table summary = [{"ID": r["ID"], "Claims": len(r["results"])} for r in all_results] table = pd.DataFrame(summary) # JSON output json_bytes = json.dumps(all_results, indent=2, ensure_ascii=False).encode("utf-8") return table, json_bytes # ---------------- Gradio UI ---------------- with gr.Blocks() as demo: gr.Markdown("# 🔎 Citation Checker (OpenAI + DeepSeek + Google CSE)\nUpload your CSV and check requirements automatically.") file_in = gr.File(label="Upload CSV", file_types=[".csv"]) run_btn = gr.Button("Run Verification", variant="primary") table_out = gr.Dataframe(label="Summary") json_out = gr.File(label="Download JSON Results") run_btn.click(fn=process_csv, inputs=file_in, outputs=[table_out, json_out]) if __name__ == "__main__": demo.launch()