hashirlodhi commited on
Commit
b333f8d
Β·
verified Β·
1 Parent(s): 647381d

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +223 -98
app.py CHANGED
@@ -2,122 +2,248 @@ import gradio as gr
2
  import openai
3
  import os
4
  from dotenv import load_dotenv
 
5
 
6
  # Load environment variables
7
  load_dotenv()
8
 
9
- # Initialize OpenAI (compatible with both old and new versions)
10
  try:
11
- # Try new OpenAI client first
12
  from openai import OpenAI
13
  client = OpenAI(api_key=os.getenv("OPENAI_API_KEY").strip())
14
  new_openai = True
15
  except ImportError:
16
- # Fall back to old version
17
  openai.api_key = os.getenv("OPENAI_API_KEY").strip()
18
  new_openai = False
19
 
20
- def analyze_text(text):
21
- """Advanced forensic analysis with improved prompt and formatted output"""
 
 
 
 
22
 
23
- expert_prompt = f"""
24
- [ROLE]
25
- You are Dr. Lexica, a world-renowned forensic linguistics expert specializing in AI/human text differentiation with 25 years of experience.
26
 
27
- [ANALYSIS TASK]
28
- Perform a comprehensive forensic analysis on the following text to determine its origin with maximum accuracy:
29
-
30
- [TEXT TO ANALYZE]
31
- {text}
32
-
33
- [ANALYSIS FRAMEWORK]
34
- 1. **Stylometric Analysis**:
35
- - Sentence structure complexity (human: varied, AI: uniform)
36
- - Lexical sophistication (human: contextual, AI: textbook-like)
37
- - Punctuation patterns (human: emotional, AI: formulaic)
38
-
39
- 2. **Cognitive Fingerprinting**:
40
- - Presence of hedges ("maybe", "I think") β†’ human
41
- - Overconfidence markers ("clearly", "undoubtedly") β†’ AI
42
- - Personal anecdotes β†’ human
43
- - Generic statements β†’ AI
44
-
45
- 3. **Semantic Forensics**:
46
- - Metaphor density (human: 3-5 per 100 words, AI: 0-2)
47
- - Contextual anchoring (human: specific references, AI: vague)
48
- - Error patterns (human: typos, AI: semantic inconsistencies)
49
-
50
- 4. **Temporal Markers**:
51
- - References to time/age (human: specific dates, AI: generic)
52
- - Cultural references (human: nuanced, AI: stereotypical)
53
-
54
- [REQUIRED OUTPUT FORMAT]
55
- # πŸ•΅οΈβ€β™‚οΈ Forensic Text Analysis Report
56
-
57
- ## πŸ” Verdict
58
- **Origin:** {{Human/AI/Inconclusive}}
59
- **Confidence Level:** {{XX%}}
60
- **Detection Score:** {{X/10}}
61
-
62
- ## πŸ“Š Key Indicators
63
- 🟒 **Human Markers Found:**
64
- - {{Marker 1}}
65
- - {{Marker 2}}
66
-
67
- πŸ”΄ **AI Markers Found:**
68
- - {{Marker 1}}
69
- - {{Marker 2}}
70
-
71
- ## 🧐 Detailed Findings
72
- ### 1️⃣ Stylometric Evidence
73
- - {{Analysis point 1}}
74
- - {{Analysis point 2}}
75
-
76
- ### 2️⃣ Cognitive Patterns
77
- - {{Analysis point 1}}
78
- - {{Analysis point 2}}
79
 
80
- ### 3️⃣ Semantic Fingerprints
81
- - {{Analysis point 1}}
82
- - {{Analysis point 2}}
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
83
 
84
- ## πŸ’‘ Expert Conclusion
85
- {{3-4 sentence authoritative conclusion with final determination. Highlight any interesting nuances or exceptional cases.}}
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
86
 
87
- ⚠️ **Disclaimer:** This analysis has {{confidence}}% accuracy based on current forensic linguistics models.
88
- """
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
89
 
90
- try:
91
- if new_openai:
92
- response = client.chat.completions.create(
93
- model="gpt-3.5-turbo", # Fixed model ID
94
- messages=[
95
- {"role": "system", "content": "You are a forensic text analysis AI specializing in detecting AI-generated content with extreme precision."},
96
- {"role": "user", "content": expert_prompt}
97
- ],
98
- temperature=0.1,
99
- max_tokens=500
100
- )
101
- return response.choices[0].message.content
102
- else:
103
- response = openai.ChatCompletion.create(
104
- model="gpt-3.5-turbo", # Fixed model ID
105
- messages=[
106
- {"role": "system", "content": "You are a forensic text analysis AI specializing in detecting AI-generated content with extreme precision."},
107
- {"role": "user", "content": expert_prompt}
108
- ],
109
- temperature=0.1,
110
- max_tokens=500
111
- )
112
- return response['choices'][0]['message']['content']
113
- except Exception as e:
114
- return f"πŸ”΄ Analysis failed. Error: {str(e)}"
115
 
116
- # Gradio Interface with enhanced UI
117
  with gr.Blocks(theme=gr.themes.Soft(primary_hue="emerald")) as app:
118
  gr.Markdown("""
119
- # πŸ”¬ AI/Human Text Forensic Analyzer
120
- *Uncover the true origin of any text using advanced linguistic forensics*
121
  """)
122
 
123
  with gr.Row():
@@ -131,10 +257,9 @@ with gr.Blocks(theme=gr.themes.Soft(primary_hue="emerald")) as app:
131
  clear_btn = gr.Button("πŸ”„ Clear")
132
 
133
  with gr.Column():
134
- output_text = gr.Markdown(label="πŸ“œ Analysis Report",
135
  elem_id="output_panel")
136
 
137
- # Improved examples showcasing different text types
138
  gr.Examples(
139
  examples=[
140
  ["Walking through the old cobblestone streets of Prague last summer, I was struck by how the golden light of dusk made the ancient buildings look like they were glowing from within - a memory that still makes me smile months later."],
@@ -147,7 +272,7 @@ with gr.Blocks(theme=gr.themes.Soft(primary_hue="emerald")) as app:
147
  )
148
 
149
  analyze_btn.click(
150
- fn=analyze_text,
151
  inputs=input_text,
152
  outputs=output_text
153
  )
 
2
  import openai
3
  import os
4
  from dotenv import load_dotenv
5
+ from typing import Dict, List
6
 
7
  # Load environment variables
8
  load_dotenv()
9
 
10
+ # Initialize OpenAI
11
  try:
 
12
  from openai import OpenAI
13
  client = OpenAI(api_key=os.getenv("OPENAI_API_KEY").strip())
14
  new_openai = True
15
  except ImportError:
 
16
  openai.api_key = os.getenv("OPENAI_API_KEY").strip()
17
  new_openai = False
18
 
19
+ class ForensicAgent:
20
+ """Base class for forensic analysis agents"""
21
+ def __init__(self, role: str, expertise: str):
22
+ self.role = role
23
+ self.expertise = expertise
24
+ self.findings = []
25
 
26
+ def analyze(self, text: str) -> Dict:
27
+ """Perform analysis and return findings"""
28
+ raise NotImplementedError
29
 
30
+ class StylometricAgent(ForensicAgent):
31
+ """Analyzes writing style characteristics"""
32
+ def __init__(self):
33
+ super().__init__("Dr. Styles", "Stylometric Analysis Expert")
34
+
35
+ def analyze(self, text: str) -> Dict:
36
+ prompt = f"""
37
+ As a {self.role}, {self.expertise}, analyze this text for stylometric patterns:
38
+
39
+ {text}
40
+
41
+ Evaluate:
42
+ 1. Sentence length variation (human: high, AI: low)
43
+ 2. Lexical diversity (human: contextual, AI: generic)
44
+ 3. Punctuation usage patterns
45
+ 4. Paragraph structure complexity
46
+
47
+ Return findings in this format:
48
+ {{
49
+ "verdict": "Human/AI/Uncertain",
50
+ "confidence": "0-100%",
51
+ "evidence": ["list", "of", "key", "findings"]
52
+ }}
53
+ """
54
+ return self._get_analysis(prompt)
55
+
56
+ def _get_analysis(self, prompt: str) -> Dict:
57
+ try:
58
+ if new_openai:
59
+ response = client.chat.completions.create(
60
+ model="gpt-4",
61
+ messages=[
62
+ {"role": "system", "content": f"You are {self.role}, {self.expertise}."},
63
+ {"role": "user", "content": prompt}
64
+ ],
65
+ temperature=0.1,
66
+ response_format={"type": "json_object"}
67
+ )
68
+ return eval(response.choices[0].message.content)
69
+ else:
70
+ response = openai.ChatCompletion.create(
71
+ model="gpt-4",
72
+ messages=[
73
+ {"role": "system", "content": f"You are {self.role}, {self.expertise}."},
74
+ {"role": "user", "content": prompt}
75
+ ],
76
+ temperature=0.1,
77
+ response_format={"type": "json_object"}
78
+ )
79
+ return eval(response['choices'][0]['message']['content'])
80
+ except Exception as e:
81
+ return {"error": str(e)}
82
 
83
+ class CognitiveAgent(ForensicAgent):
84
+ """Analyzes cognitive and psychological markers"""
85
+ def __init__(self):
86
+ super().__init__("Prof. Cognitus", "Cognitive Linguistics Specialist")
87
+
88
+ def analyze(self, text: str) -> Dict:
89
+ prompt = f"""
90
+ As {self.role}, {self.expertise}, analyze this text for cognitive markers:
91
+
92
+ {text}
93
+
94
+ Evaluate:
95
+ 1. Presence of hedging language ("perhaps", "I think")
96
+ 2. Use of personal pronouns and anecdotes
97
+ 3. Emotional expression patterns
98
+ 4. Confidence markers ("undoubtedly", "clearly")
99
+ 5. Metacognitive statements ("I'm not sure but...")
100
+
101
+ Return findings in this format:
102
+ {{
103
+ "verdict": "Human/AI/Uncertain",
104
+ "confidence": "0-100%",
105
+ "evidence": ["list", "of", "key", "findings"]
106
+ }}
107
+ """
108
+ return self._get_analysis(prompt)
109
 
110
+ class SemanticAgent(ForensicAgent):
111
+ """Analyzes semantic and contextual patterns"""
112
+ def __init__(self):
113
+ super().__init__("Dr. Semantica", "Semantic Forensics Expert")
114
+
115
+ def analyze(self, text: str) -> Dict:
116
+ prompt = f"""
117
+ As {self.role}, {self.expertise}, analyze this text for semantic patterns:
118
+
119
+ {text}
120
+
121
+ Evaluate:
122
+ 1. Metaphor and idiom density
123
+ 2. Contextual anchoring (specific vs vague references)
124
+ 3. Temporal references (specific dates vs generic time)
125
+ 4. Cultural reference depth
126
+ 5. Error patterns (typos vs semantic inconsistencies)
127
+
128
+ Return findings in this format:
129
+ {{
130
+ "verdict": "Human/AI/Uncertain",
131
+ "confidence": "0-100%",
132
+ "evidence": ["list", "of", "key", "findings"]
133
+ }}
134
+ """
135
+ return self._get_analysis(prompt)
136
 
137
+ class ForensicCrew:
138
+ """Orchestrates multiple forensic agents"""
139
+ def __init__(self):
140
+ self.agents = [
141
+ StylometricAgent(),
142
+ CognitiveAgent(),
143
+ SemanticAgent()
144
+ ]
145
+
146
+ def analyze_text(self, text: str) -> str:
147
+ """Coordinate multi-agent analysis"""
148
+ if len(text.split()) < 30:
149
+ return "⚠️ Please provide at least 150 characters for accurate analysis."
150
+
151
+ # Gather all agent findings
152
+ findings = [agent.analyze(text) for agent in self.agents]
153
+
154
+ # Have the chief analyst synthesize the results
155
+ return self._synthesize_findings(text, findings)
156
+
157
+ def _synthesize_findings(self, text: str, findings: List[Dict]) -> str:
158
+ """Have a chief analyst compile the final report"""
159
+ synthesis_prompt = f"""
160
+ [TEXT UNDER ANALYSIS]
161
+ {text}
162
+
163
+ [AGENT FINDINGS]
164
+ {findings}
165
+
166
+ As Chief Forensic Analyst Dr. Lexica, synthesize these findings into a comprehensive report:
167
+
168
+ # πŸ•΅οΈβ€β™‚οΈ Forensic Text Analysis Report (CrewAI Approach)
169
+
170
+ ## πŸ” Composite Verdict
171
+ **Origin:** {{Human/AI/Inconclusive}}
172
+ **Confidence Level:** {{XX%}}
173
+
174
+ ## πŸ“Š Agent Consensus
175
+ {self._format_agent_summary(findings)}
176
+
177
+ ## 🧐 Detailed Findings
178
+ ### 1️⃣ Stylometric Evidence
179
+ {{Summary of stylometric findings}}
180
+
181
+ ### 2️⃣ Cognitive Patterns
182
+ {{Summary of cognitive findings}}
183
+
184
+ ### 3️⃣ Semantic Fingerprints
185
+ {{Summary of semantic findings}}
186
+
187
+ ## πŸ’‘ Expert Conclusion
188
+ {{3-4 sentence authoritative conclusion synthesizing all evidence}}
189
+
190
+ ⚠️ **Disclaimer:** This analysis combines multiple forensic techniques with {self._calculate_confidence(findings)}% consensus confidence.
191
+ """
192
+
193
+ try:
194
+ if new_openai:
195
+ response = client.chat.completions.create(
196
+ model="gpt-4",
197
+ messages=[
198
+ {"role": "system", "content": "You are Dr. Lexica, Chief Forensic Analyst."},
199
+ {"role": "user", "content": synthesis_prompt}
200
+ ],
201
+ temperature=0.1,
202
+ max_tokens=800
203
+ )
204
+ return response.choices[0].message.content
205
+ else:
206
+ response = openai.ChatCompletion.create(
207
+ model="gpt-4",
208
+ messages=[
209
+ {"role": "system", "content": "You are Dr. Lexica, Chief Forensic Analyst."},
210
+ {"role": "user", "content": synthesis_prompt}
211
+ ],
212
+ temperature=0.1,
213
+ max_tokens=800
214
+ )
215
+ return response['choices'][0]['message']['content']
216
+ except Exception as e:
217
+ return f"πŸ”΄ Analysis failed. Error: {str(e)}"
218
+
219
+ def _format_agent_summary(self, findings: List[Dict]) -> str:
220
+ """Format agent findings for the report"""
221
+ summary = []
222
+ agent_names = ["Stylometric Analyst", "Cognitive Linguist", "Semantic Expert"]
223
+
224
+ for idx, finding in enumerate(findings):
225
+ if "error" in finding:
226
+ summary.append(f"πŸ”΄ {agent_names[idx]}: Error - {finding['error']}")
227
+ else:
228
+ verdict = finding.get("verdict", "Unknown")
229
+ confidence = finding.get("confidence", "0%")
230
+ summary.append(f"πŸ”΅ {agent_names[idx]}: {verdict} ({confidence} confidence)")
231
+
232
+ return "\n".join(summary)
233
+
234
+ def _calculate_confidence(self, findings: List[Dict]) -> int:
235
+ """Calculate average confidence from valid agent responses"""
236
+ valid = [int(f.get("confidence", "0%").strip('%')) for f in findings if "error" not in f]
237
+ return sum(valid) // len(valid) if valid else 0
238
 
239
+ # Initialize the forensic crew
240
+ crew = ForensicCrew()
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
241
 
242
+ # Gradio Interface
243
  with gr.Blocks(theme=gr.themes.Soft(primary_hue="emerald")) as app:
244
  gr.Markdown("""
245
+ # πŸ”¬ AI/Human Text Forensic Analyzer (CrewAI Approach)
246
+ *Multi-agent forensic analysis combining stylometric, cognitive, and semantic techniques*
247
  """)
248
 
249
  with gr.Row():
 
257
  clear_btn = gr.Button("πŸ”„ Clear")
258
 
259
  with gr.Column():
260
+ output_text = gr.Markdown(label="πŸ“œ CrewAI Analysis Report",
261
  elem_id="output_panel")
262
 
 
263
  gr.Examples(
264
  examples=[
265
  ["Walking through the old cobblestone streets of Prague last summer, I was struck by how the golden light of dusk made the ancient buildings look like they were glowing from within - a memory that still makes me smile months later."],
 
272
  )
273
 
274
  analyze_btn.click(
275
+ fn=crew.analyze_text,
276
  inputs=input_text,
277
  outputs=output_text
278
  )