abstractcore 2.4.9__py3-none-any.whl → 2.5.2__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (31) hide show
  1. abstractcore/apps/__main__.py +8 -1
  2. abstractcore/apps/deepsearch.py +644 -0
  3. abstractcore/apps/intent.py +614 -0
  4. abstractcore/assets/model_capabilities.json +50 -34
  5. abstractcore/config/__init__.py +10 -0
  6. abstractcore/{cli → config}/main.py +13 -1
  7. abstractcore/config/manager.py +355 -0
  8. abstractcore/core/session.py +46 -1
  9. abstractcore/processing/__init__.py +5 -1
  10. abstractcore/processing/basic_deepsearch.py +2173 -0
  11. abstractcore/processing/basic_intent.py +690 -0
  12. abstractcore/providers/anthropic_provider.py +1 -0
  13. abstractcore/providers/base.py +1 -0
  14. abstractcore/providers/huggingface_provider.py +95 -4
  15. abstractcore/providers/lmstudio_provider.py +14 -0
  16. abstractcore/providers/mlx_provider.py +76 -2
  17. abstractcore/providers/ollama_provider.py +6 -2
  18. abstractcore/providers/openai_provider.py +1 -0
  19. abstractcore/providers/registry.py +6 -6
  20. abstractcore/structured/handler.py +161 -1
  21. abstractcore/tools/common_tools.py +98 -3
  22. abstractcore/utils/cli.py +114 -1
  23. abstractcore/utils/version.py +1 -1
  24. {abstractcore-2.4.9.dist-info → abstractcore-2.5.2.dist-info}/METADATA +38 -18
  25. {abstractcore-2.4.9.dist-info → abstractcore-2.5.2.dist-info}/RECORD +30 -25
  26. {abstractcore-2.4.9.dist-info → abstractcore-2.5.2.dist-info}/entry_points.txt +6 -2
  27. abstractcore/cli/__init__.py +0 -9
  28. /abstractcore/{cli → config}/vision_config.py +0 -0
  29. {abstractcore-2.4.9.dist-info → abstractcore-2.5.2.dist-info}/WHEEL +0 -0
  30. {abstractcore-2.4.9.dist-info → abstractcore-2.5.2.dist-info}/licenses/LICENSE +0 -0
  31. {abstractcore-2.4.9.dist-info → abstractcore-2.5.2.dist-info}/top_level.txt +0 -0
@@ -1277,17 +1277,23 @@ def _parse_content_by_type(content_bytes: bytes, content_type: str, url: str, ex
1277
1277
  # Final fallback with error replacement
1278
1278
  text_content = content_bytes.decode('utf-8', errors='replace')
1279
1279
 
1280
- # Parse based on content type
1280
+ # Parse based on content type with fallback content detection
1281
1281
  if main_type.startswith('text/html') or main_type.startswith('application/xhtml'):
1282
1282
  return _parse_html_content(text_content, url, extract_links)
1283
1283
 
1284
1284
  elif main_type == 'application/json':
1285
1285
  return _parse_json_content(text_content)
1286
1286
 
1287
- elif main_type in ['application/xml', 'text/xml', 'application/rss+xml', 'application/atom+xml']:
1287
+ elif main_type in ['application/xml', 'text/xml', 'application/rss+xml', 'application/atom+xml', 'application/soap+xml']:
1288
1288
  return _parse_xml_content(text_content)
1289
1289
 
1290
1290
  elif main_type.startswith('text/'):
1291
+ # For generic text types, check if it's actually XML or JSON
1292
+ if text_content and text_content.strip():
1293
+ if _is_xml_content(text_content):
1294
+ return _parse_xml_content(text_content)
1295
+ elif _is_json_content(text_content):
1296
+ return _parse_json_content(text_content)
1291
1297
  return _parse_text_content(text_content, main_type)
1292
1298
 
1293
1299
  elif main_type.startswith('image/'):
@@ -1305,18 +1311,107 @@ def _parse_content_by_type(content_bytes: bytes, content_type: str, url: str, ex
1305
1311
  f"Content size: {len(content_bytes):,} bytes"
1306
1312
 
1307
1313
 
1314
+ def _is_xml_content(content: str) -> bool:
1315
+ """Detect if content is XML rather than HTML."""
1316
+ if not content:
1317
+ return False
1318
+
1319
+ content_lower = content.lower().strip()
1320
+
1321
+ # Check for XML declaration
1322
+ if content_lower.startswith('<?xml'):
1323
+ return True
1324
+
1325
+ # Check for common XML root elements without HTML indicators
1326
+ xml_indicators = ['<rss', '<feed', '<urlset', '<sitemap', '<soap:', '<xml']
1327
+ html_indicators = ['<!doctype html', '<html', '<head>', '<body>', '<div', '<span', '<p>', '<a ']
1328
+
1329
+ # Look at the first 1000 characters for indicators
1330
+ sample = content_lower[:1000]
1331
+
1332
+ # If we find HTML indicators, it's likely HTML
1333
+ if any(indicator in sample for indicator in html_indicators):
1334
+ return False
1335
+
1336
+ # If we find XML indicators without HTML indicators, it's likely XML
1337
+ if any(indicator in sample for indicator in xml_indicators):
1338
+ return True
1339
+
1340
+ # Check if it starts with a root element that looks like XML
1341
+ import re
1342
+ root_match = re.search(r'<([^?\s/>]+)', content)
1343
+ if root_match:
1344
+ root_element = root_match.group(1).lower()
1345
+ # Common XML root elements that are not HTML
1346
+ xml_roots = ['rss', 'feed', 'urlset', 'sitemap', 'configuration', 'data', 'response']
1347
+ if root_element in xml_roots:
1348
+ return True
1349
+
1350
+ return False
1351
+
1352
+
1353
+ def _is_json_content(content: str) -> bool:
1354
+ """Detect if content is JSON."""
1355
+ if not content:
1356
+ return False
1357
+
1358
+ content_stripped = content.strip()
1359
+
1360
+ # Quick check for JSON structure
1361
+ if (content_stripped.startswith('{') and content_stripped.endswith('}')) or \
1362
+ (content_stripped.startswith('[') and content_stripped.endswith(']')):
1363
+ try:
1364
+ import json
1365
+ json.loads(content_stripped)
1366
+ return True
1367
+ except (json.JSONDecodeError, ValueError):
1368
+ pass
1369
+
1370
+ return False
1371
+
1372
+
1373
+ def _get_appropriate_parser(content: str) -> str:
1374
+ """Get the appropriate BeautifulSoup parser for the content."""
1375
+ if not BS4_AVAILABLE:
1376
+ return None
1377
+
1378
+ # If lxml is available and content looks like XML, use xml parser
1379
+ if 'lxml' in BS4_PARSER and _is_xml_content(content):
1380
+ try:
1381
+ import lxml
1382
+ return 'xml'
1383
+ except ImportError:
1384
+ pass
1385
+
1386
+ # Default to the configured parser (lxml or html.parser)
1387
+ return BS4_PARSER
1388
+
1389
+
1308
1390
  def _parse_html_content(html_content: str, url: str, extract_links: bool = True) -> str:
1309
1391
  """Parse HTML content and extract meaningful information."""
1310
1392
  if not html_content:
1311
1393
  return "❌ No HTML content to parse"
1312
1394
 
1395
+ # Detect if content is actually XML (fallback detection)
1396
+ if _is_xml_content(html_content):
1397
+ return _parse_xml_content(html_content)
1398
+
1313
1399
  result_parts = []
1314
1400
  result_parts.append("🌐 HTML Document Analysis")
1315
1401
 
1316
1402
  # Use BeautifulSoup if available for better parsing
1317
1403
  if BS4_AVAILABLE:
1318
1404
  try:
1319
- soup = BeautifulSoup(html_content, BS4_PARSER)
1405
+ # Choose appropriate parser based on content analysis
1406
+ parser = _get_appropriate_parser(html_content)
1407
+
1408
+ # Suppress XML parsing warnings when using HTML parser on XML content
1409
+ import warnings
1410
+ from bs4 import XMLParsedAsHTMLWarning
1411
+
1412
+ with warnings.catch_warnings():
1413
+ warnings.filterwarnings("ignore", category=XMLParsedAsHTMLWarning)
1414
+ soup = BeautifulSoup(html_content, parser)
1320
1415
 
1321
1416
  # Extract title
1322
1417
  title = soup.find('title')
abstractcore/utils/cli.py CHANGED
@@ -39,7 +39,7 @@ except ImportError:
39
39
 
40
40
  from .. import create_llm, BasicSession
41
41
  from ..tools.common_tools import list_files, read_file, write_file, execute_command, search_files
42
- from ..processing import BasicExtractor, BasicJudge
42
+ from ..processing import BasicExtractor, BasicJudge, BasicIntentAnalyzer
43
43
 
44
44
 
45
45
  class SimpleCLI:
@@ -193,6 +193,10 @@ class SimpleCLI:
193
193
  print(" • /facts - Display in chat")
194
194
  print(" • /facts data - Save as data.jsonld")
195
195
  print(" /judge Evaluate conversation quality")
196
+ print(" /intent [participant] Analyze intents behind conversation")
197
+ print(" • /intent - Analyze all participants")
198
+ print(" • /intent user - Focus on user intents")
199
+ print(" • /intent assistant - Focus on assistant intents")
196
200
 
197
201
  print("\n⚙️ CONFIGURATION")
198
202
  print("─" * 50)
@@ -317,6 +321,17 @@ class SimpleCLI:
317
321
  elif cmd == 'judge':
318
322
  self.handle_judge()
319
323
 
324
+ elif cmd.startswith('intent'):
325
+ # Parse /intent [participant] command
326
+ parts = cmd.split()
327
+ if len(parts) == 1:
328
+ # No participant specified - analyze all
329
+ self.handle_intent(None)
330
+ else:
331
+ # Participant specified
332
+ participant = parts[1]
333
+ self.handle_intent(participant)
334
+
320
335
  elif cmd.startswith('system'):
321
336
  # Parse /system [prompt] command
322
337
  if cmd == 'system':
@@ -623,6 +638,103 @@ class SimpleCLI:
623
638
  import traceback
624
639
  traceback.print_exc()
625
640
 
641
+ def handle_intent(self, focus_participant: str = None):
642
+ """Handle /intent [participant] command - analyze intents behind conversation"""
643
+ messages = self.session.get_messages()
644
+
645
+ if len(messages) <= 1: # Only system message
646
+ print("📝 No conversation history to analyze intents from")
647
+ return
648
+
649
+ try:
650
+ if focus_participant:
651
+ print(f"🎯 Analyzing {focus_participant} intents in conversation...")
652
+ else:
653
+ print("🎯 Analyzing conversation intents for all participants...")
654
+
655
+ # Create intent analyzer using current provider for consistency
656
+ analyzer = BasicIntentAnalyzer(self.provider)
657
+
658
+ # Convert session messages to the format expected by intent analyzer
659
+ conversation_messages = [msg for msg in messages if msg.role != 'system']
660
+ message_dicts = [{"role": msg.role, "content": msg.content} for msg in conversation_messages]
661
+
662
+ if not message_dicts:
663
+ print("📝 No substantive conversation content found")
664
+ return
665
+
666
+ print(f" Processing {len(message_dicts)} messages...")
667
+
668
+ start_time = time.time()
669
+
670
+ # Analyze conversation intents
671
+ from ..processing.basic_intent import IntentDepth
672
+ results = analyzer.analyze_conversation_intents(
673
+ messages=message_dicts,
674
+ focus_participant=focus_participant,
675
+ depth=IntentDepth.UNDERLYING
676
+ )
677
+
678
+ duration = time.time() - start_time
679
+ print(f"✅ Intent analysis completed in {duration:.1f}s")
680
+
681
+ if not results:
682
+ print("❌ No intents could be analyzed from the conversation")
683
+ return
684
+
685
+ # Display results in a conversational format
686
+ print("\n🎯 CONVERSATION INTENT ANALYSIS")
687
+ print("=" * 60)
688
+
689
+ for participant, analysis in results.items():
690
+ print(f"\n👤 {participant.upper()} INTENTS:")
691
+ print("─" * 40)
692
+
693
+ # Primary Intent
694
+ primary = analysis.primary_intent
695
+ print(f"🎯 Primary Intent: {primary.intent_type.value.replace('_', ' ').title()}")
696
+ print(f" Description: {primary.description}")
697
+ print(f" Underlying Goal: {primary.underlying_goal}")
698
+ print(f" Emotional Undertone: {primary.emotional_undertone}")
699
+ print(f" Confidence: {primary.confidence:.2f} | Urgency: {primary.urgency_level:.2f}")
700
+
701
+ # Secondary Intents (show top 2 for brevity)
702
+ if analysis.secondary_intents:
703
+ print(f"\n🔄 Secondary Intents:")
704
+ for i, intent in enumerate(analysis.secondary_intents[:2], 1):
705
+ print(f" {i}. {intent.intent_type.value.replace('_', ' ').title()}")
706
+ print(f" Goal: {intent.underlying_goal}")
707
+ print(f" Confidence: {intent.confidence:.2f}")
708
+
709
+ # Key contextual factors (show top 3)
710
+ if analysis.contextual_factors:
711
+ print(f"\n🌍 Key Context Factors:")
712
+ for factor in analysis.contextual_factors[:3]:
713
+ print(f" • {factor}")
714
+
715
+ # Response approach
716
+ print(f"\n💡 Suggested Response Approach:")
717
+ # Truncate long response approaches for readability
718
+ response_approach = analysis.suggested_response_approach
719
+ if len(response_approach) > 200:
720
+ response_approach = response_approach[:197] + "..."
721
+ print(f" {response_approach}")
722
+
723
+ # Analysis metadata
724
+ print(f"\n📊 Analysis: {analysis.word_count_analyzed} words | "
725
+ f"Complexity: {analysis.intent_complexity:.2f} | "
726
+ f"Confidence: {analysis.overall_confidence:.2f} | "
727
+ f"Time: {duration:.1f}s")
728
+
729
+ print("\n" + "=" * 60)
730
+ print("💡 Note: This analysis identifies underlying motivations and goals behind communication")
731
+
732
+ except Exception as e:
733
+ print(f"❌ Intent analysis failed: {e}")
734
+ if self.debug_mode:
735
+ import traceback
736
+ traceback.print_exc()
737
+
626
738
  def _format_conversation_for_extraction(self, messages):
627
739
  """Format conversation messages for fact extraction"""
628
740
  formatted_lines = []
@@ -1337,6 +1449,7 @@ Key Commands:
1337
1449
  /compact [focus] Compress chat history with optional focus
1338
1450
  /facts [file] Extract knowledge facts
1339
1451
  /judge Evaluate conversation quality
1452
+ /intent [participant] Analyze conversation intents and motivations
1340
1453
  /system [prompt] View/change system prompt
1341
1454
 
1342
1455
  Tools: list_files, search_files, read_file, write_file, execute_command
@@ -11,4 +11,4 @@ including when the package is installed from PyPI where pyproject.toml is not av
11
11
 
12
12
  # Package version - update this when releasing new versions
13
13
  # This must be manually synchronized with the version in pyproject.toml
14
- __version__ = "2.4.9"
14
+ __version__ = "2.5.2"
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: abstractcore
3
- Version: 2.4.9
3
+ Version: 2.5.2
4
4
  Summary: Unified interface to all LLM providers with essential infrastructure for tool calling, streaming, and model management
5
5
  Author-email: Laurent-Philippe Albou <contact@abstractcore.ai>
6
6
  Maintainer-email: Laurent-Philippe Albou <contact@abstractcore.ai>
@@ -40,9 +40,11 @@ Provides-Extra: huggingface
40
40
  Requires-Dist: transformers<5.0.0,>=4.30.0; extra == "huggingface"
41
41
  Requires-Dist: torch<3.0.0,>=1.12.0; extra == "huggingface"
42
42
  Requires-Dist: llama-cpp-python<1.0.0,>=0.2.0; extra == "huggingface"
43
+ Requires-Dist: outlines>=0.1.0; extra == "huggingface"
43
44
  Provides-Extra: mlx
44
45
  Requires-Dist: mlx<1.0.0,>=0.15.0; extra == "mlx"
45
46
  Requires-Dist: mlx-lm<1.0.0,>=0.15.0; extra == "mlx"
47
+ Requires-Dist: outlines>=0.1.0; extra == "mlx"
46
48
  Provides-Extra: embeddings
47
49
  Requires-Dist: sentence-transformers<4.0.0,>=2.7.0; extra == "embeddings"
48
50
  Requires-Dist: numpy<2.0.0,>=1.20.0; extra == "embeddings"
@@ -258,7 +260,7 @@ loaded_session = BasicSession.load('conversation.json', provider=llm)
258
260
 
259
261
  ### Media Handling
260
262
 
261
- AbstractCore provides **unified media handling** across all providers with **automatic maximum resolution optimization** for best results. Upload images, PDFs, and documents using the same simple API regardless of your provider.
263
+ AbstractCore provides unified media handling across all providers with automatic resolution optimization. Upload images, PDFs, and documents using the same simple API regardless of your provider.
262
264
 
263
265
  ```python
264
266
  from abstractcore import create_llm
@@ -296,7 +298,7 @@ response = llm.generate(
296
298
  - **Smart Resolution**: Automatically uses maximum resolution supported by each model
297
299
  - **Format Support**: PNG, JPEG, GIF, WEBP, BMP, TIFF images; PDF, TXT, MD, CSV, TSV, JSON documents
298
300
  - **Office Documents**: DOCX, XLSX, PPT (with `pip install abstractcore[all]`)
299
- - **Vision Optimization**: Model-specific image processing for best vision results
301
+ - **Vision Optimization**: Model-specific image processing for vision results
300
302
 
301
303
  **Provider compatibility:**
302
304
  - **High-resolution vision**: GPT-4o (up to 4096x4096), Claude 3.5 Sonnet (up to 1568x1568)
@@ -310,11 +312,11 @@ response = llm.generate(
310
312
  - **Provider Agnostic**: Seamlessly switch between OpenAI, Anthropic, Ollama, LMStudio, MLX, HuggingFace
311
313
  - **Centralized Configuration**: Global defaults and app-specific preferences at `~/.abstractcore/config/abstractcore.json`
312
314
  - **Intelligent Media Handling**: Upload images, PDFs, and documents with automatic maximum resolution optimization
313
- - **Vision Model Support**: Smart image processing at each model's maximum capability for best results
314
- - **Document Processing**: Advanced PDF extraction (PyMuPDF4LLM), Office documents (DOCX/XLSX/PPT), CSV/TSV analysis
315
+ - **Vision Model Support**: Smart image processing at each model's maximum capability
316
+ - **Document Processing**: PDF extraction (PyMuPDF4LLM), Office documents (DOCX/XLSX/PPT), CSV/TSV analysis
315
317
  - **Unified Tools**: Consistent tool calling across all providers
316
318
  - **Session Management**: Persistent conversations with metadata, analytics, and complete serialization
317
- - **Structured Responses**: Clean, predictable output formats with Pydantic
319
+ - **Native Structured Output**: Server-side schema enforcement for Ollama and LMStudio (OpenAI and Anthropic also supported)
318
320
  - **Streaming Support**: Real-time token generation for interactive experiences
319
321
  - **Consistent Token Terminology**: Unified `input_tokens`, `output_tokens`, `total_tokens` across all providers
320
322
  - **Embeddings**: Built-in support for semantic search and RAG applications
@@ -324,12 +326,12 @@ response = llm.generate(
324
326
 
325
327
  | Provider | Status | SEED Support | Setup |
326
328
  |----------|--------|-------------|-------|
327
- | **OpenAI** | Full | Native | [Get API key](docs/prerequisites.md#openai-setup) |
328
- | **Anthropic** | Full | ⚠️ Warning* | [Get API key](docs/prerequisites.md#anthropic-setup) |
329
- | **Ollama** | Full | Native | [Install guide](docs/prerequisites.md#ollama-setup) |
330
- | **LMStudio** | Full | Native | [Install guide](docs/prerequisites.md#lmstudio-setup) |
331
- | **MLX** | Full | Native | [Setup guide](docs/prerequisites.md#mlx-setup) |
332
- | **HuggingFace** | Full | Native | [Setup guide](docs/prerequisites.md#huggingface-setup) |
329
+ | **OpenAI** | Full | Native | [Get API key](docs/prerequisites.md#openai-setup) |
330
+ | **Anthropic** | Full | Warning* | [Get API key](docs/prerequisites.md#anthropic-setup) |
331
+ | **Ollama** | Full | Native | [Install guide](docs/prerequisites.md#ollama-setup) |
332
+ | **LMStudio** | Full | Native | [Install guide](docs/prerequisites.md#lmstudio-setup) |
333
+ | **MLX** | Full | Native | [Setup guide](docs/prerequisites.md#mlx-setup) |
334
+ | **HuggingFace** | Full | Native | [Setup guide](docs/prerequisites.md#huggingface-setup) |
333
335
 
334
336
  *Anthropic doesn't support seed parameters but issues a warning when provided. Use `temperature=0.0` for more consistent outputs.
335
337
 
@@ -374,7 +376,7 @@ response = client.chat.completions.create(
374
376
  - Building web applications that need HTTP API
375
377
  - Multi-language access (not just Python)
376
378
 
377
- ## Internal CLI (Optional Interactive Testing Tool)
379
+ ## AbstractCore CLI (Optional Interactive Testing Tool)
378
380
 
379
381
  AbstractCore includes a **built-in CLI** for interactive testing, development, and conversation management. This is an internal testing tool, distinct from external agentic CLIs.
380
382
 
@@ -394,6 +396,7 @@ python -m abstractcore.utils.cli --provider anthropic --model claude-3-5-haiku-l
394
396
  - Chat history compaction and management
395
397
  - Fact extraction from conversations
396
398
  - Conversation quality evaluation (LLM-as-a-judge)
399
+ - Intent analysis and deception detection
397
400
  - Tool call testing and debugging
398
401
  - System prompt management
399
402
  - Multiple provider support
@@ -402,12 +405,13 @@ python -m abstractcore.utils.cli --provider anthropic --model claude-3-5-haiku-l
402
405
  - `/compact` - Compress chat history while preserving context
403
406
  - `/facts [file]` - Extract structured facts from conversation
404
407
  - `/judge` - Evaluate conversation quality with feedback
408
+ - `/intent [participant]` - Analyze psychological intents and detect deception
405
409
  - `/history [n]` - View conversation history
406
410
  - `/stream` - Toggle real-time streaming
407
411
  - `/system [prompt]` - Show or change system prompt
408
412
  - `/status` - Show current provider, model, and capabilities
409
413
 
410
- **Full Documentation:** [Internal CLI Guide](docs/internal-cli.md)
414
+ **Full Documentation:** [AbstractCore CLI Guide](docs/acore-cli.md)
411
415
 
412
416
  **When to use the CLI:**
413
417
  - Interactive development and testing
@@ -418,7 +422,7 @@ python -m abstractcore.utils.cli --provider anthropic --model claude-3-5-haiku-l
418
422
 
419
423
  ## Built-in Applications (Ready-to-Use CLI Tools)
420
424
 
421
- AbstractCore includes **three specialized command-line applications** for common LLM tasks. These are production-ready tools that can be used directly from the terminal without any Python programming.
425
+ AbstractCore includes **four specialized command-line applications** for common LLM tasks. These are production-ready tools that can be used directly from the terminal without any Python programming.
422
426
 
423
427
  ### Available Applications
424
428
 
@@ -427,6 +431,7 @@ AbstractCore includes **three specialized command-line applications** for common
427
431
  | **Summarizer** | Document summarization | `summarizer` |
428
432
  | **Extractor** | Entity and relationship extraction | `extractor` |
429
433
  | **Judge** | Text evaluation and scoring | `judge` |
434
+ | **Intent Analyzer** | Psychological intent analysis & deception detection | `intent` |
430
435
 
431
436
  ### Quick Usage Examples
432
437
 
@@ -445,6 +450,11 @@ extractor doc.txt --iterate 3 --mode thorough --verbose
445
450
  judge essay.txt --criteria clarity,accuracy,coherence --context "academic writing"
446
451
  judge code.py --context "code review" --format plain --verbose
447
452
  judge proposal.md --custom-criteria has_examples,covers_risks --output assessment.json
453
+
454
+ # Intent analysis with psychological insights and deception detection
455
+ intent conversation.txt --focus-participant user --depth comprehensive
456
+ intent email.txt --format plain --context document --verbose
457
+ intent chat_log.json --conversation-mode --provider lmstudio --model qwen/qwen3-30b-a3b-2507
448
458
  ```
449
459
 
450
460
  ### Installation & Setup
@@ -459,6 +469,7 @@ pip install abstractcore[all]
459
469
  summarizer --help
460
470
  extractor --help
461
471
  judge --help
472
+ intent --help
462
473
  ```
463
474
 
464
475
  ### Alternative Usage Methods
@@ -468,11 +479,13 @@ judge --help
468
479
  summarizer document.txt
469
480
  extractor report.pdf
470
481
  judge essay.md
482
+ intent conversation.txt
471
483
 
472
484
  # Method 2: Via Python module
473
485
  python -m abstractcore.apps summarizer document.txt
474
486
  python -m abstractcore.apps extractor report.pdf
475
487
  python -m abstractcore.apps judge essay.md
488
+ python -m abstractcore.apps intent conversation.txt
476
489
  ```
477
490
 
478
491
  ### Key Parameters
@@ -514,10 +527,11 @@ python -m abstractcore.apps judge essay.md
514
527
 
515
528
  ### Full Documentation
516
529
 
517
- Each application has comprehensive documentation with examples and advanced usage:
530
+ Each application has documentation with examples and usage information:
518
531
 
519
532
  - **[Summarizer Guide](docs/apps/basic-summarizer.md)** - Document summarization with multiple strategies
520
533
  - **[Extractor Guide](docs/apps/basic-extractor.md)** - Entity and relationship extraction
534
+ - **[Intent Analyzer Guide](docs/apps/basic-intent.md)** - Psychological intent analysis and deception detection
521
535
  - **[Judge Guide](docs/apps/basic-judge.md)** - Text evaluation and scoring systems
522
536
 
523
537
  **When to use the apps:**
@@ -551,6 +565,10 @@ abstractcore --set-console-log-level NONE # Disable console logging
551
565
  abstractcore --enable-file-logging # Save logs to files
552
566
  abstractcore --enable-debug-logging # Full debug mode
553
567
 
568
+ # Configure vision for image analysis with text-only models
569
+ abstractcore --set-vision-provider ollama qwen2.5vl:7b
570
+ abstractcore --set-vision-provider lmstudio qwen/qwen3-vl-4b
571
+
554
572
  # Set API keys as needed
555
573
  abstractcore --set-api-key openai sk-your-key-here
556
574
  abstractcore --set-api-key anthropic your-anthropic-key
@@ -662,7 +680,7 @@ llm = create_llm("anthropic", model="claude-3.5-sonnet")
662
680
  response = llm.generate(analysis_prompt, media=documents)
663
681
 
664
682
  # Automatic format handling:
665
- # - PDF: Advanced text extraction with PyMuPDF4LLM
683
+ # - PDF: Text extraction with PyMuPDF4LLM
666
684
  # - Excel: Table parsing with pandas
667
685
  # - PowerPoint: Slide content extraction with unstructured
668
686
  ```
@@ -715,6 +733,8 @@ review = llm.generate(
715
733
  print(f"{review.title}: {review.rating}/5")
716
734
  ```
717
735
 
736
+ [Learn more about Structured Output](docs/structured-output.md)
737
+
718
738
  ### 7. Universal API Server
719
739
 
720
740
  ```bash
@@ -770,7 +790,7 @@ pip install abstractcore[all]
770
790
 
771
791
  **Media processing extras:**
772
792
  ```bash
773
- # For advanced PDF processing
793
+ # For PDF processing
774
794
  pip install pymupdf4llm
775
795
 
776
796
  # For Office documents (DOCX, XLSX, PPT)
@@ -1,25 +1,28 @@
1
1
  abstractcore/__init__.py,sha256=A7Gbn_C-robdWLLQXjtTyWsoaXDGIblSFmLRV_ni6O8,1934
2
2
  abstractcore/apps/__init__.py,sha256=sgNOv3lYyOWNBC-w6GnRN6aILGCbdkQtNcuQdJz5ghE,31
3
- abstractcore/apps/__main__.py,sha256=041daYkoIE1VLEO19IZC5nNIDOQZWNgpB7ogJ3SOlsE,1585
3
+ abstractcore/apps/__main__.py,sha256=fV9cGU99K4lGRsPNOLkh8qrDjH3JtMEWNlBiZrvI5Kk,1974
4
4
  abstractcore/apps/app_config_utils.py,sha256=5GIvXnD996LFIV3-BpfkqII6UqYlStm7ZCgmqDEN8dc,890
5
+ abstractcore/apps/deepsearch.py,sha256=UlmuBS9T4yNsz0V_iY08GNNDTstsI5OJNNV6c8CU6AE,23191
5
6
  abstractcore/apps/extractor.py,sha256=OfiqB9l_alH9xCGb6zOD__QJkDjdKOlLZngriVgmn7c,23749
7
+ abstractcore/apps/intent.py,sha256=5ie_H9_K_ZxlA0oCu7ROUrsgwfzDNFgVUyBNec6YVRE,22813
6
8
  abstractcore/apps/judge.py,sha256=nOgxvn-BbhNY6xU9AlTeD1yidTh73AiVlSN7hQCVE2M,23169
7
9
  abstractcore/apps/summarizer.py,sha256=9aD6KH21w-tv_wGp9MaO2uyJuaU71OemW7KpqrG5t6w,14669
8
10
  abstractcore/architectures/__init__.py,sha256=-4JucAM7JkMWShWKkePoclxrUHRKgaG36UTguJihE0U,1046
9
11
  abstractcore/architectures/detection.py,sha256=Cxap1pL6qOJjyY22Vc4hzbLALTuuBisPT5UaMotousk,10025
10
12
  abstractcore/architectures/enums.py,sha256=9vIv2vDBEKhxwzwH9iaSAyf-iVj3p8y9loMeN_mYTJ8,3821
11
13
  abstractcore/assets/architecture_formats.json,sha256=CIf6SaR_IJs1D7Uvd1K3zWngIXJ_yq3DM_IE3wnpCHY,16076
12
- abstractcore/assets/model_capabilities.json,sha256=iUkDiljyZUZzPlpYCOFgStXyc6e7dvOfReYQ0HFrX9Q,49703
14
+ abstractcore/assets/model_capabilities.json,sha256=AJwF1tmaGGl4P-UTbKX6awsgw7W543UN2TuqhC3y_Ss,50236
13
15
  abstractcore/assets/session_schema.json,sha256=hMCVrq3KSyVExrMGzuykf7bU-z6WyIVuEGU8du9_zUY,10570
14
- abstractcore/cli/__init__.py,sha256=rUjLjZSK3wENSw4g_iN43Bc2i5cggcEmj4NPXBMohdc,241
15
- abstractcore/cli/main.py,sha256=cZBOY3Cj7a4SUxqp7p3FeuS-iUnCdYOf1-v4CICIni0,32073
16
- abstractcore/cli/vision_config.py,sha256=jJzO4zBexh8SqSKp6YKOXdMDSv4AL4Ztl5Xi-5c4KyY,17869
16
+ abstractcore/config/__init__.py,sha256=4mHX5z5Sq8R8xh78tb9jjZLaz_oBNW1eh914OsdDTxs,318
17
+ abstractcore/config/main.py,sha256=U9zz-h9OvadqW9pBRRf999gVZKtBWsk27oPJtiJa8Qk,32646
18
+ abstractcore/config/manager.py,sha256=mo-cpT-jNfQmfTSe9LcalwE1WqjCyvNQexPIqNMS6sc,13098
19
+ abstractcore/config/vision_config.py,sha256=jJzO4zBexh8SqSKp6YKOXdMDSv4AL4Ztl5Xi-5c4KyY,17869
17
20
  abstractcore/core/__init__.py,sha256=2h-86U4QkCQ4gzZ4iRusSTMlkODiUS6tKjZHiEXz6rM,684
18
21
  abstractcore/core/enums.py,sha256=BhkVnHC-X1_377JDmqd-2mnem9GdBLqixWlYzlP_FJU,695
19
22
  abstractcore/core/factory.py,sha256=ec7WGW2JKK-dhDplziTAeRkebEUFymtEEZ_bS5qkpqY,2798
20
23
  abstractcore/core/interface.py,sha256=-VAY0nlsTnWN_WghiuMC7iE7xUdZfYOg6KlgrAPi14Y,14086
21
24
  abstractcore/core/retry.py,sha256=wNlUAxfmvdO_uVWb4iqkhTqd7O1oRwXxqvVQaLXQOw0,14538
22
- abstractcore/core/session.py,sha256=fdqhnufCWrV022RjQ-Xfb1KFv_s9-GzetSSR-QuXv-Q,36452
25
+ abstractcore/core/session.py,sha256=thqG8zWICKpPeCJi5IoKbMhBDOH4RJlTfUjymP14TFY,38249
23
26
  abstractcore/core/types.py,sha256=jj44i07kMjdg9FQ3mA_fK6r_M0Lcgt1RQpy1Ra5w-eI,4578
24
27
  abstractcore/embeddings/__init__.py,sha256=hR3xZyqcRm4c2pq1dIa5lxj_-Bk70Zad802JQN4joWo,637
25
28
  abstractcore/embeddings/manager.py,sha256=uFVbRPHx_R-kVMVA7N7_7EzeUmCJCeN9Dv0EV8Jko24,52245
@@ -43,27 +46,29 @@ abstractcore/media/processors/pdf_processor.py,sha256=qniYt7cTYYPVRi_cS1IsXztOld
43
46
  abstractcore/media/processors/text_processor.py,sha256=E28FtT2_jzsvMIDwZi6aVWuu_pSyAPSBa96fe4YYcU8,21092
44
47
  abstractcore/media/utils/__init__.py,sha256=30-CTif91iRKOXJ4njGiduWAt-xp31U7NafMBNvgdO0,460
45
48
  abstractcore/media/utils/image_scaler.py,sha256=QrYqoNQc8tzGu7I9Sf_E-Iv7ei2oLh714AGiX3yACNM,11338
46
- abstractcore/processing/__init__.py,sha256=t6hiakQjcZROT4pw9ZFt2q6fF3vf5VpdMKG2EWlsFd8,540
49
+ abstractcore/processing/__init__.py,sha256=QcACEnhnHKYCkFL1LNOW_uqBrwkTAmz5A61N4K2dyu0,988
50
+ abstractcore/processing/basic_deepsearch.py,sha256=dzJQtH4k44XY9tvG0Z4JIlYt_s7HpbLdSPScha-t7vk,101036
47
51
  abstractcore/processing/basic_extractor.py,sha256=3x-3BdIHgLvqLnLF6K1-P4qVaLIpAnNIIutaJi7lDQM,49832
52
+ abstractcore/processing/basic_intent.py,sha256=wD99Z7fE2RiYk6oyTZXojUbv-bz8HhKFIuIHYLLTw54,32455
48
53
  abstractcore/processing/basic_judge.py,sha256=tKWJrg_tY4vCHzWgXxz0ZjgLXBYYfpMcpG7vl03hJcM,32218
49
54
  abstractcore/processing/basic_summarizer.py,sha256=XHNxMQ_8aLStTeUo6_2JaThlct12Htpz7ORmm0iuJsg,25495
50
55
  abstractcore/providers/__init__.py,sha256=n-2RMNm3QpKxHw9EOjv8icRMRnfJp5Xg0uSVzHCW3BI,1222
51
- abstractcore/providers/anthropic_provider.py,sha256=R87Z_DNNdeA4LMSxx84pqo8saKFz38dHCJMBpc-rL70,21552
52
- abstractcore/providers/base.py,sha256=YfrqM3c7wLT19vspL7goUO6Bv-z1691ZkCM2wxvQX4s,51501
53
- abstractcore/providers/huggingface_provider.py,sha256=pgpeSwpwyNB_5GDyLEz2OSTu9me-GAJzQ116dGtpCvQ,49012
54
- abstractcore/providers/lmstudio_provider.py,sha256=odT6luVR3POVcq2ZqkINLyLoCAu_YGpLLj3fEddNliU,21021
55
- abstractcore/providers/mlx_provider.py,sha256=sDgxf_kVJJwxprQWVef9w2CLOu2dLES8D0Vf5tY6PzE,18463
56
- abstractcore/providers/ollama_provider.py,sha256=1bE80NCj_TQADxRCiu9luyLuI_gZe2EO5pCKoC4VhQM,21740
57
- abstractcore/providers/openai_provider.py,sha256=1s7JJalyIBOvLB7UAUwXbTc2aYrYSWg7hJjKGnCX1qU,23313
58
- abstractcore/providers/registry.py,sha256=fKFrN6Z3o5Gi0dfwvXDPtrrJXDjx9oPSfjWjZf-NJBc,15883
56
+ abstractcore/providers/anthropic_provider.py,sha256=wXzRgW1AJCRX5dovXHVRTNxL96vycr7Ug9omKnLjPzo,21588
57
+ abstractcore/providers/base.py,sha256=gWlkchUZBXgcJAKNV8U1hROUGGw8MdDIuLHQM2LRx8Y,51530
58
+ abstractcore/providers/huggingface_provider.py,sha256=mTjpdZlC49QCMqsDHEabTnQbX21z7MNV77Dv9hs_RiM,53696
59
+ abstractcore/providers/lmstudio_provider.py,sha256=jzNMngjRtpw4lgdF66i5h22QIPWXvritezcJndetu7A,21632
60
+ abstractcore/providers/mlx_provider.py,sha256=1gI1KXJdKcgjiaivk7LpuBScpYgsVJ9YEikm-gCChoo,22156
61
+ abstractcore/providers/ollama_provider.py,sha256=VfPn6y87Jjih1MhFsHhijtv1AhbefhwSh4_Z2eAKc4o,21975
62
+ abstractcore/providers/openai_provider.py,sha256=kV1YXjzKyqJMQhmn9kG7AwQ-ssu8PipFwXdmmuosR98,23346
63
+ abstractcore/providers/registry.py,sha256=oqEaKjF2nuPiw9W0u6DM7TJgm4P2i94aKZRb8Ma6PqM,16002
59
64
  abstractcore/providers/streaming.py,sha256=VnffBV_CU9SAKzghL154OoFyEdDsiLwUNXPahyU41Bw,31342
60
65
  abstractcore/server/__init__.py,sha256=1DSAz_YhQtnKv7sNi5TMQV8GFujctDOabgvAdilQE0o,249
61
66
  abstractcore/server/app.py,sha256=7pG5ZkZqYNnyby4jyvp3_NKl5nNDmZpOhv_-F8Jruy4,96580
62
67
  abstractcore/structured/__init__.py,sha256=VXRQHGcm-iaYnLOBPin2kyhvhhQA0kaGt_pcNDGsE_8,339
63
- abstractcore/structured/handler.py,sha256=Vb15smiR81JGDXX2RLkY2Exuj67J7a6C-xwVrZoXp0I,17134
68
+ abstractcore/structured/handler.py,sha256=hcUe_fZcwx0O3msLqFiOsj6-jbq3S-ZQa9c1nRIZvuo,24622
64
69
  abstractcore/structured/retry.py,sha256=BN_PvrWybyU1clMy2cult1-TVxFSMaVqiCPmmXvA5aI,3805
65
70
  abstractcore/tools/__init__.py,sha256=oh6vG0RdM1lqUtOp95mLrTsWLh9VmhJf5_FVjGIP5_M,2259
66
- abstractcore/tools/common_tools.py,sha256=GkUSnBum3zMm9M-Zd9LlJQmlDp1XDssC7z8ItUcbloc,91692
71
+ abstractcore/tools/common_tools.py,sha256=sfCuwZX3mG229yZRAgaLlDrVpGCVfdH_Uq5tZUVw6n8,95122
67
72
  abstractcore/tools/core.py,sha256=lUUGihyceiRYlKUFvEMig9jWFF563d574mSDbYYD3fM,4777
68
73
  abstractcore/tools/handler.py,sha256=GmDenXAJkhceWSGlhvuF90aMb2301tRTh6WxGwBQifc,12022
69
74
  abstractcore/tools/parser.py,sha256=1r5nmEEp1Rid3JU6ct-s3lP-eCln67fvXG5HCjqiRew,27740
@@ -71,15 +76,15 @@ abstractcore/tools/registry.py,sha256=cN3nbPEK6L2vAd9740MIFf2fitW_4WHpQfK4KvQjnT
71
76
  abstractcore/tools/syntax_rewriter.py,sha256=c3NSTvUF3S3ho5Cwjp7GJJdibeYAI6k3iaBwhKcpTfo,17318
72
77
  abstractcore/tools/tag_rewriter.py,sha256=UGFMBj2QKwm12j8JQ6oc2C_N3ZeNqz9Enz4VkEIrS0c,20338
73
78
  abstractcore/utils/__init__.py,sha256=29mMc3jV_suEPBn7W8Yw_wqcdvFP-083ws5AUFJVM28,676
74
- abstractcore/utils/cli.py,sha256=btuTIECrBPV4cdoWoE-N1rkzcrq--dhwKbtZTQhvwok,65175
79
+ abstractcore/utils/cli.py,sha256=tO7S-iVSZavxJaX7OTruNAmF3lJz9eCDORK8Dm7FdgA,70558
75
80
  abstractcore/utils/message_preprocessor.py,sha256=GdHkm6tmrgjm3PwHRSCjIsq1XLkbhy_vDEKEUE7OiKY,6028
76
81
  abstractcore/utils/self_fixes.py,sha256=QEDwNTW80iQM4ftfEY3Ghz69F018oKwLM9yeRCYZOvw,5886
77
82
  abstractcore/utils/structured_logging.py,sha256=Vm-HviSa42G9DJCWmaEv4a0QG3NMsADD3ictLOs4En0,19952
78
83
  abstractcore/utils/token_utils.py,sha256=eLwFmJ68p9WMFD_MHLMmeJRW6Oqx_4hKELB8FNQ2Mnk,21097
79
- abstractcore/utils/version.py,sha256=no3N7qA8I5XGeoI1AfM5yAVEAnvR87_qtMTqqRVPDVc,605
80
- abstractcore-2.4.9.dist-info/licenses/LICENSE,sha256=PI2v_4HMvd6050uDD_4AY_8PzBnu2asa3RKbdDjowTA,1078
81
- abstractcore-2.4.9.dist-info/METADATA,sha256=rmaOtujlK0uq0n8YOFg1wht75czvj4beh9Wpv6obTVQ,31907
82
- abstractcore-2.4.9.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
83
- abstractcore-2.4.9.dist-info/entry_points.txt,sha256=UdVmchBC_Lt3H4Vlkt5js-QDAkVlBbkCu1yCsswk-KE,454
84
- abstractcore-2.4.9.dist-info/top_level.txt,sha256=DiNHBI35SIawW3N9Z-z0y6cQYNbXd32pvBkW0RLfScs,13
85
- abstractcore-2.4.9.dist-info/RECORD,,
84
+ abstractcore/utils/version.py,sha256=GC9cH32Kxl_Gm71B9JyHaV8605RVj_YHzLdOS6AjFM0,605
85
+ abstractcore-2.5.2.dist-info/licenses/LICENSE,sha256=PI2v_4HMvd6050uDD_4AY_8PzBnu2asa3RKbdDjowTA,1078
86
+ abstractcore-2.5.2.dist-info/METADATA,sha256=VeTcJ285fQCo75pDmpjGmnllxlWHH6JvyfSYeN_o8Y4,32893
87
+ abstractcore-2.5.2.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
88
+ abstractcore-2.5.2.dist-info/entry_points.txt,sha256=jXNdzeltVs23A2JM2e2HOiAHldHrsnud3EvPI5VffOs,658
89
+ abstractcore-2.5.2.dist-info/top_level.txt,sha256=DiNHBI35SIawW3N9Z-z0y6cQYNbXd32pvBkW0RLfScs,13
90
+ abstractcore-2.5.2.dist-info/RECORD,,
@@ -1,10 +1,14 @@
1
1
  [console_scripts]
2
- abstractcore = abstractcore.cli.main:main
2
+ abstractcore = abstractcore.config.main:main
3
3
  abstractcore-chat = abstractcore.utils.cli:main
4
- abstractcore-config = abstractcore.cli.main:main
4
+ abstractcore-config = abstractcore.config.main:main
5
+ abstractcore-deepsearch = abstractcore.apps.deepsearch:main
5
6
  abstractcore-extractor = abstractcore.apps.extractor:main
7
+ abstractcore-intent = abstractcore.apps.intent:main
6
8
  abstractcore-judge = abstractcore.apps.judge:main
7
9
  abstractcore-summarizer = abstractcore.apps.summarizer:main
10
+ deepsearch = abstractcore.apps.deepsearch:main
8
11
  extractor = abstractcore.apps.extractor:main
12
+ intent = abstractcore.apps.intent:main
9
13
  judge = abstractcore.apps.judge:main
10
14
  summarizer = abstractcore.apps.summarizer:main
@@ -1,9 +0,0 @@
1
- """
2
- AbstractCore CLI Module
3
-
4
- Provides command-line interface for AbstractCore configuration and tools.
5
- """
6
-
7
- from .vision_config import handle_vision_commands, add_vision_arguments
8
-
9
- __all__ = ['handle_vision_commands', 'add_vision_arguments']
File without changes