-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathapp.py
More file actions
168 lines (129 loc) Β· 4.91 KB
/
app.py
File metadata and controls
168 lines (129 loc) Β· 4.91 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
"""
Gradio UI for Chase the Source.
"""
import logging
import gradio as gr
from config import settings
from graph import run_source_check
from schemas.models import AttributionType, SourceAttribution, SourceType
# Configure logging
logging.basicConfig(
level=getattr(logging, settings.log_level),
format="%(asctime)s - %(name)s - %(levelname)s - %(message)s",
)
logger = logging.getLogger(__name__)
def format_attribution_output(result: SourceAttribution) -> tuple[str, str, str]:
"""Format attribution result for display in Gradio."""
# Claim display
claim_text = f"**Extracted Claim:**\n\n{result.claim}"
# Attribution display with color coding
attribution_colors = {
AttributionType.DIRECT: "π’",
AttributionType.PARAPHRASE: "π‘",
AttributionType.CONTRADICTION: "π΄",
AttributionType.NOT_FOUND: "βͺ",
}
attribution_text = f"""**Attribution:** {attribution_colors.get(result.attribution, "")} {result.attribution.value.upper()}
**Summary:**
{result.summary}
"""
if result.relies_on_secondary_only:
attribution_text += "\nβ οΈ *This result relies only on secondary reporting.*"
# Best source highlight
if result.best_source:
best = result.best_source
attribution_text += f"\n\n**Best Source:** {best.evidence.source_title} ({best.evidence.source_type.value})"
# Sources display
sources_text = ""
if result.evidence_list:
for i, assessment in enumerate(result.evidence_list, 1):
e = assessment.evidence
source_type_label = {
SourceType.PRIMARY: "π Primary",
SourceType.ORIGINAL_REPORTING: "π° Original Reporting",
SourceType.SECONDARY: "π Secondary",
SourceType.UNKNOWN: "β Unknown",
}.get(e.source_type, "Unknown")
attribution_emoji = {
"direct": "π―",
"paraphrase": "π",
"contradiction": "β",
}.get(assessment.attribution, "")
sources_text += f"""
---
### Source {i}: {e.source_title}
**Source Type:** {source_type_label}
**URL:** [{e.source_url}]({e.source_url})
**Quote:**
> {e.verbatim_quote}
**Attribution:** {attribution_emoji} {assessment.attribution}
**Reasoning:** {assessment.reasoning}
"""
else:
sources_text = "*No relevant sources found.*"
return claim_text, attribution_text, sources_text
def process_input(text: str, source_url: str | None = None) -> tuple[str, str, str]:
"""
Process user input through the source attribution pipeline.
Args:
text: User-provided text to analyze
source_url: Optional URL of the page the text came from (to avoid self-sourcing)
Returns:
Tuple of (claim, attribution, sources) formatted strings
"""
if not text or len(text.strip()) < 10:
return ("**Error:** Please provide at least 10 characters of text.", "", "")
logger.info(f"Processing input: {len(text)} characters; source_url provided={bool(source_url)}")
try:
result = run_source_check(text, source_url)
attribution = result.get("result")
if not attribution:
return ("**Error:** Failed to produce a result.", "", "")
return format_attribution_output(attribution)
except Exception as e:
logger.error(f"Processing error: {e}")
return (f"**Error:** An error occurred during processing: {e}", "", "")
# Build Gradio interface
with gr.Blocks(title="Chase the Source", theme=gr.themes.Soft()) as app:
gr.Markdown(
"""
# π Chase the Source
Paste an article excerpt, social post, or commentary below.
The system will extract a factual claim and trace it back to original sources.
"""
)
with gr.Row():
input_text = gr.Textbox(
label="Input Text",
placeholder="Paste text containing a factual claim...",
lines=5,
max_lines=10,
)
source_url = gr.Textbox(
label="Origin URL (optional)",
placeholder="Paste the URL the text came from to avoid self-citation",
lines=1,
)
submit_btn = gr.Button("Chase the Source", variant="primary")
with gr.Row():
with gr.Column():
claim_output = gr.Markdown(label="Extracted Claim")
with gr.Column():
attribution_output = gr.Markdown(label="Attribution")
sources_output = gr.Markdown(label="Sources")
submit_btn.click(
fn=process_input,
inputs=[input_text, source_url],
outputs=[claim_output, attribution_output, sources_output],
show_progress="full",
)
gr.Markdown(
"""
---
*This is an MVP for demonstration purposes. Results should be independently verified.*
"""
)
if __name__ == "__main__":
app.launch(
server_name=settings.gradio_server_name, server_port=settings.gradio_server_port
)