Diego Carpintero commited on
Commit
3dd5cf3
1 Parent(s): 27e7df9

refactor workflow

Browse files
Files changed (3) hide show
  1. config/agents.yaml +15 -2
  2. minerva.ipynb +87 -200
  3. tools.py +13 -10
config/agents.yaml CHANGED
@@ -1,9 +1,14 @@
1
  ocr_agent:
2
  assignment: >
3
  You are an OCR specialist. Your role is to:
4
- 1. Extract text from an image path using pytesseract
5
  2. Clean and format the extracted text for further analysis
6
 
 
 
 
 
 
7
  content_agent:
8
  assignment: >
9
  You are a content analysis specialist. Your role is to:
@@ -26,4 +31,12 @@ summary_agent:
26
  2. Highlight the most important points that users need to know
27
  3. Provide actionable recommendations
28
  4. Shorten your message into one paragraph
29
- 5. End your summary with the label 'ANALYSIS_COMPLETE' when done
 
 
 
 
 
 
 
 
 
1
  ocr_agent:
2
  assignment: >
3
  You are an OCR specialist. Your role is to:
4
+ 1. Extract text from an image path using the registered function for this task
5
  2. Clean and format the extracted text for further analysis
6
 
7
+ url_agent:
8
+ assignment: >
9
+ You are a URL agent. Your role is to:
10
+ 1. Check whether a URL is safe using the registered function for this task
11
+
12
  content_agent:
13
  assignment: >
14
  You are a content analysis specialist. Your role is to:
 
31
  2. Highlight the most important points that users need to know
32
  3. Provide actionable recommendations
33
  4. Shorten your message into one paragraph
34
+ 5. Reply 'COMPLETE' when the task is complete
35
+
36
+ user_proxy:
37
+ assignment: >
38
+ Your role is to coordinate the available agents to carry out a scam assessment process. These are the steps to follow:
39
+ 1. Extract text from an image
40
+ 2. Analyze the text content for scam patterns
41
+ 3. Synthesize the analyses and make final determination
42
+ 4. Generate a summary of the final determination
minerva.ipynb CHANGED
@@ -28,7 +28,7 @@
28
  },
29
  {
30
  "cell_type": "code",
31
- "execution_count": 7,
32
  "metadata": {},
33
  "outputs": [
34
  {
@@ -45,7 +45,7 @@
45
  },
46
  {
47
  "cell_type": "code",
48
- "execution_count": 8,
49
  "metadata": {},
50
  "outputs": [
51
  {
@@ -65,7 +65,7 @@
65
  },
66
  {
67
  "cell_type": "code",
68
- "execution_count": 9,
69
  "metadata": {},
70
  "outputs": [],
71
  "source": [
@@ -89,7 +89,7 @@
89
  },
90
  {
91
  "cell_type": "code",
92
- "execution_count": 10,
93
  "metadata": {},
94
  "outputs": [],
95
  "source": [
@@ -108,7 +108,7 @@
108
  },
109
  {
110
  "cell_type": "code",
111
- "execution_count": 18,
112
  "metadata": {},
113
  "outputs": [],
114
  "source": [
@@ -119,38 +119,43 @@
119
  "\n",
120
  " ocr_agent = autogen.AssistantAgent(\n",
121
  " name=\"OCR_Specialist\",\n",
 
122
  " system_message=config['ocr_agent']['assignment'],\n",
123
  " llm_config=llm_config\n",
124
  " )\n",
125
  "\n",
126
- " url_checker_agent = autogen.AssistantAgent(\n",
127
- " name=\"URL_Checker\",\n",
128
- " system_message=config['url_checker_agent']['assignment'],\n",
 
129
  " llm_config=llm_config\n",
130
  " )\n",
131
  " \n",
132
  " content_agent = autogen.AssistantAgent(\n",
133
  " name=\"Content_Analyst\",\n",
 
134
  " system_message=config['content_agent']['assignment'],\n",
135
  " llm_config=llm_config\n",
136
  " )\n",
137
  "\n",
138
  " decision_agent = autogen.AssistantAgent(\n",
139
  " name=\"Decision_Maker\",\n",
 
140
  " system_message=config['decision_agent']['assignment'],\n",
141
  " llm_config=llm_config\n",
142
  " )\n",
143
  "\n",
144
  " summary_agent = autogen.AssistantAgent(\n",
145
  " name=\"Summary_Agent\",\n",
146
- " description=\"Generates a summary of the findings\",\n",
147
  " system_message=config['summary_agent']['assignment'],\n",
148
  " llm_config=llm_config\n",
149
  " )\n",
150
  "\n",
151
  " user_proxy = autogen.UserProxyAgent(\n",
152
  " name=\"user_proxy\",\n",
153
- " is_termination_msg=lambda msg: \"ANALYSIS_COMPLETE\" in msg.get(\"content\", \"\"),\n",
 
154
  " human_input_mode=\"NEVER\",\n",
155
  " max_consecutive_auto_reply=10,\n",
156
  " )\n",
@@ -161,12 +166,13 @@
161
  " return tools.ocr(image_path)\n",
162
  " \n",
163
  " @user_proxy.register_for_execution()\n",
164
- " @url_checker_agent.register_for_llm(description=\"Checks if a URL is safe\")\n",
165
- " def is_url_safe(url: str) -> str:\n",
166
  " return tools.is_url_safe(url)\n",
167
  "\n",
168
  "\n",
169
- " return ocr_agent, url_checker_agent, content_agent, decision_agent, summary_agent, user_proxy"
 
170
  ]
171
  },
172
  {
@@ -178,33 +184,40 @@
178
  },
179
  {
180
  "cell_type": "code",
181
- "execution_count": 19,
182
  "metadata": {},
183
  "outputs": [],
184
  "source": [
185
  "class ScamDetectionWorkflow:\n",
186
  " def __init__(self):\n",
187
- " self.ocr_agent, self.url_checker_agent, self.content_agent, self.decision_agent, self.summary_agent, self.user_proxy = create_agents()\n",
 
188
  " \n",
189
  " def analyze(self, image_path):\n",
190
  " \"\"\"Coordinate the multi-agent analysis.\n",
191
  " \"\"\"\n",
192
  " \n",
193
  " groupchat = autogen.GroupChat(\n",
194
- " agents=[self.ocr_agent, self.url_checker_agent, self.content_agent, self.decision_agent, self.summary_agent, self.user_proxy],\n",
 
195
  " messages=[],\n",
196
  " max_round=15,\n",
 
197
  " )\n",
198
- " manager = autogen.GroupChatManager(groupchat=groupchat)\n",
199
  "\n",
 
 
 
 
 
 
 
 
 
200
  " messages = self.user_proxy.initiate_chat(\n",
201
  " manager,\n",
202
- " message=f\"\"\"\n",
203
- " 1. OCR Agent: Extract text from this image: {image_path}\n",
204
- " 2. Extract any URL from the text and check if it is safe\n",
205
- " 2. Content Agent: Evaluate the messaging and claims\n",
206
- " 3. Decision Maker: Synthesize all analyses and make final determination\n",
207
- " 4. Summarize the findings\"\"\",\n",
208
  " )\n",
209
  "\n",
210
  " return messages"
@@ -212,7 +225,7 @@
212
  },
213
  {
214
  "cell_type": "code",
215
- "execution_count": 20,
216
  "metadata": {},
217
  "outputs": [
218
  {
@@ -238,7 +251,7 @@
238
  },
239
  {
240
  "cell_type": "code",
241
- "execution_count": 21,
242
  "metadata": {},
243
  "outputs": [
244
  {
@@ -247,20 +260,21 @@
247
  "text": [
248
  "\u001b[33muser_proxy\u001b[0m (to chat_manager):\n",
249
  "\n",
 
250
  "\n",
251
- " 1. OCR Agent: Extract text from this image: ./samples/02.giftcard.message.scam.png\n",
252
- " 2. Extract any URL from the text and check if it is safe\n",
253
- " 2. Content Agent: Evaluate the messaging and claims\n",
254
- " 3. Decision Maker: Synthesize all analyses and make final determination\n",
255
- " 4. Summarize the findings\n",
256
- "\n",
257
- "--------------------------------------------------------------------------------\n",
258
  "\u001b[32m\n",
259
  "Next speaker: OCR_Specialist\n",
260
  "\u001b[0m\n",
261
  "\u001b[33mOCR_Specialist\u001b[0m (to chat_manager):\n",
262
  "\n",
263
- "\u001b[32m***** Suggested tool call (call_nImrxy4iboAGXWRO6F3HlXco): ocr *****\u001b[0m\n",
264
  "Arguments: \n",
265
  "{\"image_path\":\"./samples/02.giftcard.message.scam.png\"}\n",
266
  "\u001b[32m********************************************************************\u001b[0m\n",
@@ -270,18 +284,12 @@
270
  "Next speaker: user_proxy\n",
271
  "\u001b[0m\n",
272
  "\u001b[35m\n",
273
- ">>>>>>>> EXECUTING FUNCTION ocr...\u001b[0m\n"
274
- ]
275
- },
276
- {
277
- "name": "stdout",
278
- "output_type": "stream",
279
- "text": [
280
  "\u001b[33muser_proxy\u001b[0m (to chat_manager):\n",
281
  "\n",
282
  "\u001b[33muser_proxy\u001b[0m (to chat_manager):\n",
283
  "\n",
284
- "\u001b[32m***** Response from calling tool (call_nImrxy4iboAGXWRO6F3HlXco) *****\u001b[0m\n",
285
  "Congratulations!\n",
286
  "You've won a $1,000\n",
287
  "Walmart gift card. Go\n",
@@ -293,68 +301,17 @@
293
  "\n",
294
  "--------------------------------------------------------------------------------\n",
295
  "\u001b[32m\n",
296
- "Next speaker: OCR_Specialist\n",
297
  "\u001b[0m\n",
298
- "\u001b[33mOCR_Specialist\u001b[0m (to chat_manager):\n",
299
  "\n",
300
- "\u001b[32m***** Suggested tool call (call_38Y8iIQ4rrgZCLEHmHziBXZa): check_url_safety *****\u001b[0m\n",
301
  "Arguments: \n",
302
  "{\"url\": \"http://bit.ly/123456\"}\n",
303
- "\u001b[32m*********************************************************************************\u001b[0m\n",
304
- "\u001b[32m***** Suggested tool call (call_RpsQS2ep2q9ahungdLSb5Xp2): evaluate_messaging *****\u001b[0m\n",
305
- "Arguments: \n",
306
- "{\"text\": \"Congratulations! You've won a $1,000 Walmart gift card. Go http://bit.ly/123456 tp claim now.\"}\n",
307
- "\u001b[32m***********************************************************************************\u001b[0m\n",
308
- "\n",
309
- "--------------------------------------------------------------------------------\n",
310
- "\u001b[32m\n",
311
- "Next speaker: user_proxy\n",
312
- "\u001b[0m\n",
313
- "\u001b[33muser_proxy\u001b[0m (to chat_manager):\n",
314
- "\n",
315
- "\u001b[33muser_proxy\u001b[0m (to chat_manager):\n",
316
- "\n",
317
- "\u001b[32m***** Response from calling tool (call_38Y8iIQ4rrgZCLEHmHziBXZa) *****\u001b[0m\n",
318
- "Error: Function check_url_safety not found.\n",
319
- "\u001b[32m**********************************************************************\u001b[0m\n",
320
- "\n",
321
- "--------------------------------------------------------------------------------\n",
322
- "\u001b[33muser_proxy\u001b[0m (to chat_manager):\n",
323
- "\n",
324
- "\u001b[32m***** Response from calling tool (call_RpsQS2ep2q9ahungdLSb5Xp2) *****\u001b[0m\n",
325
- "Error: Function evaluate_messaging not found.\n",
326
- "\u001b[32m**********************************************************************\u001b[0m\n",
327
- "\n",
328
- "--------------------------------------------------------------------------------\n",
329
- "\u001b[32m\n",
330
- "Next speaker: OCR_Specialist\n",
331
- "\u001b[0m\n",
332
- "\u001b[33mOCR_Specialist\u001b[0m (to chat_manager):\n",
333
- "\n",
334
- "It seems that there was an error attempting to check the URL for safety and evaluate the messaging. However, I can summarize the findings based on the extracted text.\n",
335
- "\n",
336
- "### Extracted Text:\n",
337
- "- **Message**: \"Congratulations! You've won a $1,000 Walmart gift card. Go to http://bit.ly/123456 to claim now.\"\n",
338
- "\n",
339
- "### Findings:\n",
340
- "1. **Claim Analysis**: The message makes a claim of winning a significant prize ($1,000 Walmart gift card), which is a common tactic used in scams to lure individuals into providing personal information or engaging in fraudulent activities.\n",
341
- " \n",
342
- "2. **URL Safety**: The URL provided is a shortened link (bit.ly), which can often be used to mask the true destination. Shortened URLs can lead to unsafe sites, making it essential to check the link before clicking.\n",
343
- "\n",
344
- "### Conclusion:\n",
345
- "Based on the extracted text and the nature of the claims, the messaging appears to be a scam, typical of phishing attempts. The claim of winning a large gift card is insincere and aims to deceive recipients. \n",
346
- "\n",
347
- "If you need to proceed with URL safety checks or further evaluations, please inform me!\n",
348
- "\n",
349
- "--------------------------------------------------------------------------------\n",
350
- "\u001b[32m\n",
351
- "Next speaker: URL_Checker\n",
352
- "\u001b[0m\n",
353
- "\u001b[33mURL_Checker\u001b[0m (to chat_manager):\n",
354
- "\n",
355
- "\u001b[32m***** Suggested tool call (call_tA5lFFHPQVNLNdYtB0Ugvunr): is_url_safe *****\u001b[0m\n",
356
  "Arguments: \n",
357
- "{\"url\":\"http://bit.ly/123456\"}\n",
358
  "\u001b[32m****************************************************************************\u001b[0m\n",
359
  "\n",
360
  "--------------------------------------------------------------------------------\n",
@@ -362,78 +319,25 @@
362
  "Next speaker: user_proxy\n",
363
  "\u001b[0m\n",
364
  "\u001b[35m\n",
365
- ">>>>>>>> EXECUTING FUNCTION is_url_safe...\u001b[0m\n",
 
 
 
 
366
  "\u001b[33muser_proxy\u001b[0m (to chat_manager):\n",
367
  "\n",
368
  "\u001b[33muser_proxy\u001b[0m (to chat_manager):\n",
369
  "\n",
370
- "\u001b[32m***** Response from calling tool (call_tA5lFFHPQVNLNdYtB0Ugvunr) *****\u001b[0m\n",
371
- "Error: Error checking URL safety: 400 Client Error: Bad Request for url: https://safebrowsing.googleapis.com/v4/threatMatches:find?key=AIzaSyAgHquJ24dNaT5Tspr1vcDmcVHPSOnjgFc\n",
372
  "\u001b[32m**********************************************************************\u001b[0m\n",
373
  "\n",
374
  "--------------------------------------------------------------------------------\n",
375
- "\u001b[32m\n",
376
- "Next speaker: OCR_Specialist\n",
377
- "\u001b[0m\n",
378
- "\u001b[33mOCR_Specialist\u001b[0m (to chat_manager):\n",
379
- "\n",
380
- "It seems there was an issue while attempting to verify the safety of the URL provided (http://bit.ly/123456). \n",
381
- "\n",
382
- "### Summary of Findings:\n",
383
- "1. **Message Content**:\n",
384
- " - The extracted message suggests that the recipient has won a $1,000 Walmart gift card, which is a likely scam intended to lure individuals into divulging personal information or clicking on potentially harmful links.\n",
385
- "\n",
386
- "2. **URL Safety**:\n",
387
- " - The URL is a shortened link which hides the actual destination, a common tactic used in scams. Without confirming its safety through a reliable service, caution should be exercised.\n",
388
- "\n",
389
- "### Conclusion:\n",
390
- "The messaging appears to be fraudulent, designed to deceive individuals into believing they have won a prize. Any engagement with such messages, including clicking on links, is not advisable. \n",
391
- "\n",
392
- "If you need additional assistance or have other questions, feel free to ask!\n",
393
- "\n",
394
- "--------------------------------------------------------------------------------\n",
395
- "\u001b[32m\n",
396
- "Next speaker: URL_Checker\n",
397
- "\u001b[0m\n",
398
- "\u001b[33mURL_Checker\u001b[0m (to chat_manager):\n",
399
- "\n",
400
- "### Summary of Findings:\n",
401
- "\n",
402
- "1. **Message Content**:\n",
403
- " - The extracted message states: \"Congratulations! You've won a $1,000 Walmart gift card. Go to http://bit.ly/123456 to claim now.\"\n",
404
- " - This message is a classic scam tactic aiming to entice recipients by claiming they have won a significant prize. Such claims are often associated with phishing attempts designed to acquire personal information.\n",
405
- "\n",
406
- "2. **URL Safety**:\n",
407
- " - The provided URL is a shortened link (bit.ly), which can mask the actual destination. This makes it hard to assess the link’s safety without further checks. Shortened URLs are often used in scams, and clicking on them can lead to unsafe websites.\n",
408
- "\n",
409
- "### Conclusion:\n",
410
- "The messaging appears to be fraudulent and aimed at deceiving individuals. It is highly recommended not to engage with such messages or click on any links provided.\n",
411
- "\n",
412
- "If you require further analysis or have other inquiries, please let me know!\n",
413
- "\n",
414
- "--------------------------------------------------------------------------------\n",
415
- "\u001b[32m\n",
416
- "Next speaker: Content_Analyst\n",
417
- "\u001b[0m\n",
418
- "\u001b[33mContent_Analyst\u001b[0m (to chat_manager):\n",
419
- "\n",
420
- "### Final Summary of Findings:\n",
421
- "\n",
422
- "1. **Message Content**:\n",
423
- " - The message claims, \"Congratulations! You've won a $1,000 Walmart gift card. Go to http://bit.ly/123456 to claim now.\"\n",
424
- " - This is a common scam tactic that tempts recipients with the lure of a significant prize, often leading to phishing attempts aimed at stealing personal information.\n",
425
- "\n",
426
- "2. **URL Safety**:\n",
427
- " - The URL is a shortened link (bit.ly), which conceals its true destination. It is important to approach such links with caution, as they are frequently utilized in scams and can direct users to potentially harmful sites.\n",
428
- "\n",
429
- "3. **Urgency and Pressure Tactics**:\n",
430
- " - The phrase \"claim now\" creates a sense of urgency, a typical pressure tactic used in scams to prompt immediate action without thoughtful consideration.\n",
431
- "\n",
432
- "4. **Inconsistencies**:\n",
433
- " - Legitimate communications from companies like Walmart typically do not deliver prizes via unsolicited messages. There’s no prior contact or context provided indicating that the recipient has entered any contests with Walmart.\n",
434
  "\n",
435
- "### Conclusion:\n",
436
- "The evidence strongly suggests that this message is a scam. It is advisable not to click any links or provide personal information in response to such offers. If further assistance is needed or you have more queries, please let me know!\n",
 
437
  "\n",
438
  "--------------------------------------------------------------------------------\n",
439
  "\u001b[32m\n",
@@ -441,28 +345,19 @@
441
  "\u001b[0m\n",
442
  "\u001b[33mDecision_Maker\u001b[0m (to chat_manager):\n",
443
  "\n",
444
- "### Final Determination on Scam Probability: High\n",
445
- "\n",
446
- "### Detailed Explanation of the Decision:\n",
447
  "\n",
448
- "1. **Identifiable Scam Characteristics**:\n",
449
- " - The message employs common elements of scams, such as congratulatory language for a large prize that the recipient has not entered to win. Scams frequently use similar tactics to generate excitement and encourage immediate action.\n",
450
- " \n",
451
- "2. **Use of Shortened URLs**:\n",
452
- " - The presence of a shortened URL (http://bit.ly/123456) is particularly concerning, as such links can obscure the destination website. Many scams utilize shortened URLs because they can lead to phishing websites without showing the actual link, making it harder for recipients to evaluate the safety of the link before clicking.\n",
453
  "\n",
454
- "3. **Urgency**:\n",
455
- " - The phrasing \"claim now\" creates a sense of urgency and pressures recipients to act quickly, a common tactic employed by scammers to bypass critical thinking, prompting them to take immediate action without verifying the legitimacy of the offer.\n",
456
  "\n",
457
- "4. **Lack of Context and Prior Engagement**:\n",
458
- " - There is no prior context that suggests the recipient would have any connection to the reward being offered. Legitimate promotional offers typically have a clear and contextually relevant background, often requiring prior engagement with the company.\n",
459
  "\n",
460
- "5. **Trustworthiness of the Source**:\n",
461
- " - Major retailers like Walmart do not conduct their promotions through unsolicited messages promising prizes without prior engagement. This adds to the legitimacy concerns surrounding the communication.\n",
462
  "\n",
463
- "Given the combination of these factors, the probability of this being a scam is assessed to be high. Recipients are highly advised to ignore such messages, refrain from clicking on any links, and avoid providing any personal information in response.\n",
464
  "\n",
465
- "If further clarity or assistance is needed, please feel free to reach out!\n",
466
  "\n",
467
  "--------------------------------------------------------------------------------\n",
468
  "\u001b[32m\n",
@@ -470,9 +365,9 @@
470
  "\u001b[0m\n",
471
  "\u001b[33mSummary_Agent\u001b[0m (to chat_manager):\n",
472
  "\n",
473
- "This analysis confirms that the message claiming you won a $1,000 Walmart gift card is a high-probability scam. Key indicators include the use of congratulatory language for a prize you did not enter to win, a suspicious shortened URL (http://bit.ly/123456), and high-pressure tactics urging immediate action. Legitimate communications from companies like Walmart typically do not come unsolicited, meaning this message lacks context and authenticity. **Recommendation:** Do not click any links or provide personal information in response to such messages. Remain cautious and report any suspicious communications. \n",
474
  "\n",
475
- "ANALYSIS_COMPLETE\n",
476
  "\n",
477
  "--------------------------------------------------------------------------------\n",
478
  "\u001b[32m\n",
@@ -488,26 +383,25 @@
488
  },
489
  {
490
  "cell_type": "code",
491
- "execution_count": 22,
492
  "metadata": {},
493
  "outputs": [
494
  {
495
  "name": "stdout",
496
  "output_type": "stream",
497
  "text": [
498
- "{'content': 'This analysis confirms that the message claiming you won a $1,000 '\n",
499
- " 'Walmart gift card is a high-probability scam. Key indicators '\n",
500
- " 'include the use of congratulatory language for a prize you did '\n",
501
- " 'not enter to win, a suspicious shortened URL '\n",
502
- " '(http://bit.ly/123456), and high-pressure tactics urging '\n",
503
- " 'immediate action. Legitimate communications from companies like '\n",
504
- " 'Walmart typically do not come unsolicited, meaning this message '\n",
505
- " 'lacks context and authenticity. **Recommendation:** Do not click '\n",
506
- " 'any links or provide personal information in response to such '\n",
507
- " 'messages. Remain cautious and report any suspicious '\n",
508
  " 'communications. \\n'\n",
509
  " '\\n'\n",
510
- " 'ANALYSIS_COMPLETE',\n",
511
  " 'name': 'Summary_Agent',\n",
512
  " 'role': 'user'}\n"
513
  ]
@@ -521,7 +415,7 @@
521
  },
522
  {
523
  "cell_type": "code",
524
- "execution_count": 46,
525
  "metadata": {},
526
  "outputs": [],
527
  "source": [
@@ -551,13 +445,6 @@
551
  "source": [
552
  "results.summary"
553
  ]
554
- },
555
- {
556
- "cell_type": "code",
557
- "execution_count": null,
558
- "metadata": {},
559
- "outputs": [],
560
- "source": []
561
  }
562
  ],
563
  "metadata": {
 
28
  },
29
  {
30
  "cell_type": "code",
31
+ "execution_count": 1,
32
  "metadata": {},
33
  "outputs": [
34
  {
 
45
  },
46
  {
47
  "cell_type": "code",
48
+ "execution_count": 2,
49
  "metadata": {},
50
  "outputs": [
51
  {
 
65
  },
66
  {
67
  "cell_type": "code",
68
+ "execution_count": 17,
69
  "metadata": {},
70
  "outputs": [],
71
  "source": [
 
89
  },
90
  {
91
  "cell_type": "code",
92
+ "execution_count": 18,
93
  "metadata": {},
94
  "outputs": [],
95
  "source": [
 
108
  },
109
  {
110
  "cell_type": "code",
111
+ "execution_count": 19,
112
  "metadata": {},
113
  "outputs": [],
114
  "source": [
 
119
  "\n",
120
  " ocr_agent = autogen.AssistantAgent(\n",
121
  " name=\"OCR_Specialist\",\n",
122
+ " description=\"Extracts text from an image\",\n",
123
  " system_message=config['ocr_agent']['assignment'],\n",
124
  " llm_config=llm_config\n",
125
  " )\n",
126
  "\n",
127
+ " url_agent = autogen.AssistantAgent(\n",
128
+ " name=\"URL_Agent\",\n",
129
+ " description=\"Checks if a URL is safe\",\n",
130
+ " system_message=config['url_agent']['assignment'],\n",
131
  " llm_config=llm_config\n",
132
  " )\n",
133
  " \n",
134
  " content_agent = autogen.AssistantAgent(\n",
135
  " name=\"Content_Analyst\",\n",
136
+ " description=\"Analyzes the text for scam patterns\",\n",
137
  " system_message=config['content_agent']['assignment'],\n",
138
  " llm_config=llm_config\n",
139
  " )\n",
140
  "\n",
141
  " decision_agent = autogen.AssistantAgent(\n",
142
  " name=\"Decision_Maker\",\n",
143
+ " description=\"Synthesizes the analyses and make final determination\",\n",
144
  " system_message=config['decision_agent']['assignment'],\n",
145
  " llm_config=llm_config\n",
146
  " )\n",
147
  "\n",
148
  " summary_agent = autogen.AssistantAgent(\n",
149
  " name=\"Summary_Agent\",\n",
150
+ " description=\"Generate a summary of the final determination\",\n",
151
  " system_message=config['summary_agent']['assignment'],\n",
152
  " llm_config=llm_config\n",
153
  " )\n",
154
  "\n",
155
  " user_proxy = autogen.UserProxyAgent(\n",
156
  " name=\"user_proxy\",\n",
157
+ " is_termination_msg=lambda x: \"COMPLETE\" in x.get(\"content\", \"\"),\n",
158
+ " #is_termination_msg=lambda x: x.get(\"content\", \"\") and x.get(\"content\", \"\").rstrip().endswith(\"TERMINATE\"),\n",
159
  " human_input_mode=\"NEVER\",\n",
160
  " max_consecutive_auto_reply=10,\n",
161
  " )\n",
 
166
  " return tools.ocr(image_path)\n",
167
  " \n",
168
  " @user_proxy.register_for_execution()\n",
169
+ " @content_agent.register_for_llm(description=\"Checks if a URL is safe\")\n",
170
+ " def url_checker (url: str) -> str:\n",
171
  " return tools.is_url_safe(url)\n",
172
  "\n",
173
  "\n",
174
+ " #return ocr_agent, url_agent, content_agent, decision_agent, summary_agent, user_proxy\n",
175
+ " return ocr_agent, content_agent, decision_agent, summary_agent, user_proxy"
176
  ]
177
  },
178
  {
 
184
  },
185
  {
186
  "cell_type": "code",
187
+ "execution_count": 21,
188
  "metadata": {},
189
  "outputs": [],
190
  "source": [
191
  "class ScamDetectionWorkflow:\n",
192
  " def __init__(self):\n",
193
+ " #self.ocr_agent, self.url_agent, self.content_agent, self.decision_agent, self.summary_agent, self.user_proxy = create_agents()\n",
194
+ " self.ocr_agent, self.content_agent, self.decision_agent, self.summary_agent, self.user_proxy = create_agents()\n",
195
  " \n",
196
  " def analyze(self, image_path):\n",
197
  " \"\"\"Coordinate the multi-agent analysis.\n",
198
  " \"\"\"\n",
199
  " \n",
200
  " groupchat = autogen.GroupChat(\n",
201
+ " #agents=[self.ocr_agent, self.url_agent, self.content_agent, self.decision_agent, self.summary_agent, self.user_proxy],\n",
202
+ " agents=[self.ocr_agent, self.content_agent, self.decision_agent, self.summary_agent, self.user_proxy],\n",
203
  " messages=[],\n",
204
  " max_round=15,\n",
205
+ " #speaker_selection_method=\"round_robin\",\n",
206
  " )\n",
207
+ " manager = autogen.GroupChatManager(groupchat=groupchat, llm_config=llm_config)\n",
208
  "\n",
209
+ " # 2. URL Agent: Check if a URL is safe\n",
210
+ " #messages = self.user_proxy.initiate_chat(\n",
211
+ " # manager,\n",
212
+ " # message=f\"\"\"\n",
213
+ " # 1. OCR Agent: Extract text from this image: {image_path}\n",
214
+ " # 2. Content Agent: Evaluate the messaging and claims\n",
215
+ " # 3. Decision Maker: Synthesize all analyses and make final determination\n",
216
+ " # 4. Summarize the findings\"\"\",\n",
217
+ " #)\n",
218
  " messages = self.user_proxy.initiate_chat(\n",
219
  " manager,\n",
220
+ " message=f\"\"\"does the content of the image in {image_path} represent a scam?\"\"\",\n",
 
 
 
 
 
221
  " )\n",
222
  "\n",
223
  " return messages"
 
225
  },
226
  {
227
  "cell_type": "code",
228
+ "execution_count": 22,
229
  "metadata": {},
230
  "outputs": [
231
  {
 
251
  },
252
  {
253
  "cell_type": "code",
254
+ "execution_count": 23,
255
  "metadata": {},
256
  "outputs": [
257
  {
 
260
  "text": [
261
  "\u001b[33muser_proxy\u001b[0m (to chat_manager):\n",
262
  "\n",
263
+ "does the content of the image in ./samples/02.giftcard.message.scam.png represent a scam?\n",
264
  "\n",
265
+ "--------------------------------------------------------------------------------\n"
266
+ ]
267
+ },
268
+ {
269
+ "name": "stdout",
270
+ "output_type": "stream",
271
+ "text": [
272
  "\u001b[32m\n",
273
  "Next speaker: OCR_Specialist\n",
274
  "\u001b[0m\n",
275
  "\u001b[33mOCR_Specialist\u001b[0m (to chat_manager):\n",
276
  "\n",
277
+ "\u001b[32m***** Suggested tool call (call_CRjjATgsjHAUQECgDKBauJNe): ocr *****\u001b[0m\n",
278
  "Arguments: \n",
279
  "{\"image_path\":\"./samples/02.giftcard.message.scam.png\"}\n",
280
  "\u001b[32m********************************************************************\u001b[0m\n",
 
284
  "Next speaker: user_proxy\n",
285
  "\u001b[0m\n",
286
  "\u001b[35m\n",
287
+ ">>>>>>>> EXECUTING FUNCTION ocr...\u001b[0m\n",
 
 
 
 
 
 
288
  "\u001b[33muser_proxy\u001b[0m (to chat_manager):\n",
289
  "\n",
290
  "\u001b[33muser_proxy\u001b[0m (to chat_manager):\n",
291
  "\n",
292
+ "\u001b[32m***** Response from calling tool (call_CRjjATgsjHAUQECgDKBauJNe) *****\u001b[0m\n",
293
  "Congratulations!\n",
294
  "You've won a $1,000\n",
295
  "Walmart gift card. Go\n",
 
301
  "\n",
302
  "--------------------------------------------------------------------------------\n",
303
  "\u001b[32m\n",
304
+ "Next speaker: Content_Analyst\n",
305
  "\u001b[0m\n",
306
+ "\u001b[33mContent_Analyst\u001b[0m (to chat_manager):\n",
307
  "\n",
308
+ "\u001b[32m***** Suggested tool call (call_68tUF9q6PDAu3QtPpPFp0dBr): url_checker *****\u001b[0m\n",
309
  "Arguments: \n",
310
  "{\"url\": \"http://bit.ly/123456\"}\n",
311
+ "\u001b[32m****************************************************************************\u001b[0m\n",
312
+ "\u001b[32m***** Suggested tool call (call_grNDKKmo9xObrUQ3kUTdlqsK): url_checker *****\u001b[0m\n",
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
313
  "Arguments: \n",
314
+ "{\"url\": \"http://bit.ly/123456\"}\n",
315
  "\u001b[32m****************************************************************************\u001b[0m\n",
316
  "\n",
317
  "--------------------------------------------------------------------------------\n",
 
319
  "Next speaker: user_proxy\n",
320
  "\u001b[0m\n",
321
  "\u001b[35m\n",
322
+ ">>>>>>>> EXECUTING FUNCTION url_checker...\u001b[0m\n",
323
+ "request_body: {'client': {'clientId': 'minerva', 'clientVersion': '0.1.0'}, 'threatInfo': {'threatTypes': ['MALWARE', 'SOCIAL_ENGINEERING', 'UNWANTED_SOFTWARE', 'POTENTIALLY_HARMFUL_APPLICATION'], 'platformTypes': ['ANY_PLATFORM'], 'threatEntryTypes': ['URL'], 'threatEntries': [{'url': 'http://bit.ly/123456'}]}}\n",
324
+ "\u001b[35m\n",
325
+ ">>>>>>>> EXECUTING FUNCTION url_checker...\u001b[0m\n",
326
+ "request_body: {'client': {'clientId': 'minerva', 'clientVersion': '0.1.0'}, 'threatInfo': {'threatTypes': ['MALWARE', 'SOCIAL_ENGINEERING', 'UNWANTED_SOFTWARE', 'POTENTIALLY_HARMFUL_APPLICATION'], 'platformTypes': ['ANY_PLATFORM'], 'threatEntryTypes': ['URL'], 'threatEntries': [{'url': 'http://bit.ly/123456'}]}}\n",
327
  "\u001b[33muser_proxy\u001b[0m (to chat_manager):\n",
328
  "\n",
329
  "\u001b[33muser_proxy\u001b[0m (to chat_manager):\n",
330
  "\n",
331
+ "\u001b[32m***** Response from calling tool (call_68tUF9q6PDAu3QtPpPFp0dBr) *****\u001b[0m\n",
332
+ "[true, []]\n",
333
  "\u001b[32m**********************************************************************\u001b[0m\n",
334
  "\n",
335
  "--------------------------------------------------------------------------------\n",
336
+ "\u001b[33muser_proxy\u001b[0m (to chat_manager):\n",
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
337
  "\n",
338
+ "\u001b[32m***** Response from calling tool (call_grNDKKmo9xObrUQ3kUTdlqsK) *****\u001b[0m\n",
339
+ "[true, []]\n",
340
+ "\u001b[32m**********************************************************************\u001b[0m\n",
341
  "\n",
342
  "--------------------------------------------------------------------------------\n",
343
  "\u001b[32m\n",
 
345
  "\u001b[0m\n",
346
  "\u001b[33mDecision_Maker\u001b[0m (to chat_manager):\n",
347
  "\n",
348
+ "Based on the analysis of the content in the image, the probability of it being a scam is very high.\n",
 
 
349
  "\n",
350
+ "### Explanation:\n",
 
 
 
 
351
  "\n",
352
+ "1. **Content of the Message**: The message claims that the recipient has \"won a $1,000 Walmart gift card.\" Such claims are typical of scam messages. Scammers often use phrases that suggest the receiver has won something unexpectedly, aiming to entice the recipient to click on a link.\n",
 
353
  "\n",
354
+ "2. **Link Included**: The presence of a shortened URL (http://bit.ly/123456) raises red flags. Scammers often use URL shorteners to obscure the true destination of the link, making it harder for recipients to determine if the link leads to a legitimate site or a malicious one.\n",
 
355
  "\n",
356
+ "3. **Verification of URL**: While the URL seems to be valid, the use of bit.ly doesn't guarantee it's a safe destination. Shortened URLs can lead to phishing platforms or websites designed to steal personal information.\n",
 
357
  "\n",
358
+ "4. **Common Scam Patterns**: The elements of the message align with known scam tactics—such as the promise of free money, urgency in claiming the prize, and the use of official brand names to lure victims.\n",
359
  "\n",
360
+ "In conclusion, considering the suspicious offer of a gift card, the use of a shortened link, and the overall context typical of scams, it is highly likely that the content of the image represents a scam.\n",
361
  "\n",
362
  "--------------------------------------------------------------------------------\n",
363
  "\u001b[32m\n",
 
365
  "\u001b[0m\n",
366
  "\u001b[33mSummary_Agent\u001b[0m (to chat_manager):\n",
367
  "\n",
368
+ "The analysis of the message claiming a $1,000 Walmart gift card indicates a high probability that it's a scam. Key warning signs include the unsolicited nature of the \"win,\" a shortened URL that conceals the link's real destination, and common scam tactics that use enticing offers to trick victims. To protect yourself, do not click on any links in such messages, avoid sharing personal information, and report suspicious content to relevant authorities. Stay vigilant and skeptical of unsolicited offers claiming you've won something. \n",
369
  "\n",
370
+ "COMPLETE\n",
371
  "\n",
372
  "--------------------------------------------------------------------------------\n",
373
  "\u001b[32m\n",
 
383
  },
384
  {
385
  "cell_type": "code",
386
+ "execution_count": 10,
387
  "metadata": {},
388
  "outputs": [
389
  {
390
  "name": "stdout",
391
  "output_type": "stream",
392
  "text": [
393
+ "{'content': 'The message claiming \"You\\'ve won a $1,000 Walmart gift card\" '\n",
394
+ " 'raises several red flags indicating a high probability of being a '\n",
395
+ " 'scam. It notifies the recipient about an unsolicited prize, '\n",
396
+ " 'creates urgency by urging immediate action, and includes a '\n",
397
+ " 'shortened link (bit.ly) that obscures its real destination and '\n",
398
+ " 'often indicates a potential threat. Users should avoid clicking '\n",
399
+ " 'on such links and be skeptical of unsolicited prize '\n",
400
+ " 'notifications. **Actionable recommendation:** Do not engage with '\n",
401
+ " 'or follow links in unsolicited messages and report suspicious '\n",
 
402
  " 'communications. \\n'\n",
403
  " '\\n'\n",
404
+ " 'COMPLETE',\n",
405
  " 'name': 'Summary_Agent',\n",
406
  " 'role': 'user'}\n"
407
  ]
 
415
  },
416
  {
417
  "cell_type": "code",
418
+ "execution_count": 11,
419
  "metadata": {},
420
  "outputs": [],
421
  "source": [
 
445
  "source": [
446
  "results.summary"
447
  ]
 
 
 
 
 
 
 
448
  }
449
  ],
450
  "metadata": {
tools.py CHANGED
@@ -12,7 +12,7 @@ class Tools:
12
  load_dotenv(find_dotenv())
13
 
14
  self.safebrowsing_key = os.getenv("SAFEBROWSING_API_KEY")
15
- self.api_base_url = "https://safebrowsing.googleapis.com/v4"
16
  self.client_id = "minerva"
17
  self.client_version = "0.1.0"
18
  self.threat_types = [
@@ -41,15 +41,15 @@ class Tools:
41
  except requests.exceptions.RequestException as e:
42
  return url # Return original URL if expansion fails
43
 
44
- def is_url_safe(self, url: str) -> Tuple[bool, List[Dict[str, str]]]:
45
  """Check if URL is safe using Google Safe Browsing API
46
  """
47
  if not self.safebrowsing_key:
48
  raise ValueError("SAFEBROWSING_API_KEY is missing.")
49
 
50
- api_endpoint = f"{self.api_base_url}/threatMatches:find?key={self.safebrowsing_key}"
51
- expanded_url = self.expand_url(url)
52
-
53
  request_body = {
54
  "client": {
55
  "clientId": self.client_id,
@@ -60,14 +60,18 @@ class Tools:
60
  "platformTypes": ["ANY_PLATFORM"],
61
  "threatEntryTypes": ["URL"],
62
  "threatEntries": [
63
- {"url": url},
64
- {"url": expanded_url} if expanded_url != url else {}
65
  ]
66
  }
67
  }
 
 
 
 
 
68
 
69
  try:
70
- response = requests.post(api_endpoint, json=request_body)
71
  response.raise_for_status()
72
 
73
  result = response.json()
@@ -80,8 +84,7 @@ class Tools:
80
  for match in result["matches"]:
81
  threats.append({
82
  "threat_type": match.get("threatType"),
83
- "platform_type": match.get("platformType"),
84
- "threat_entry_type": match.get("threatEntryType")
85
  })
86
 
87
  return False, threats
 
12
  load_dotenv(find_dotenv())
13
 
14
  self.safebrowsing_key = os.getenv("SAFEBROWSING_API_KEY")
15
+ self.base_url = "https://safebrowsing.googleapis.com/v4"
16
  self.client_id = "minerva"
17
  self.client_version = "0.1.0"
18
  self.threat_types = [
 
41
  except requests.exceptions.RequestException as e:
42
  return url # Return original URL if expansion fails
43
 
44
+ def is_url_safe(self, target_url: str) -> Tuple[bool, List[Dict[str, str]]]:
45
  """Check if URL is safe using Google Safe Browsing API
46
  """
47
  if not self.safebrowsing_key:
48
  raise ValueError("SAFEBROWSING_API_KEY is missing.")
49
 
50
+ safe_endpoint = f"{self.base_url}/threatMatches:find?key={self.safebrowsing_key}"
51
+ expanded_url = self.expand_url(target_url)
52
+
53
  request_body = {
54
  "client": {
55
  "clientId": self.client_id,
 
60
  "platformTypes": ["ANY_PLATFORM"],
61
  "threatEntryTypes": ["URL"],
62
  "threatEntries": [
63
+ {"url": target_url}
 
64
  ]
65
  }
66
  }
67
+
68
+ if expanded_url != target_url:
69
+ request_body["threatInfo"]["threatEntries"].append({"url": expanded_url})
70
+
71
+ print(f"request_body: {request_body}")
72
 
73
  try:
74
+ response = requests.post(safe_endpoint, json=request_body)
75
  response.raise_for_status()
76
 
77
  result = response.json()
 
84
  for match in result["matches"]:
85
  threats.append({
86
  "threat_type": match.get("threatType"),
87
+ "threat_url": match.get("threat", {}).get("url"),
 
88
  })
89
 
90
  return False, threats