abstractcore 2.4.2__py3-none-any.whl → 2.4.4__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.
- abstractcore/apps/app_config_utils.py +19 -0
- abstractcore/apps/summarizer.py +85 -56
- abstractcore/architectures/detection.py +15 -4
- abstractcore/assets/architecture_formats.json +1 -1
- abstractcore/assets/model_capabilities.json +420 -11
- abstractcore/core/interface.py +2 -0
- abstractcore/core/session.py +4 -0
- abstractcore/embeddings/manager.py +54 -16
- abstractcore/media/__init__.py +116 -148
- abstractcore/media/auto_handler.py +363 -0
- abstractcore/media/base.py +456 -0
- abstractcore/media/capabilities.py +335 -0
- abstractcore/media/types.py +300 -0
- abstractcore/media/vision_fallback.py +260 -0
- abstractcore/providers/anthropic_provider.py +18 -1
- abstractcore/providers/base.py +187 -0
- abstractcore/providers/huggingface_provider.py +111 -12
- abstractcore/providers/lmstudio_provider.py +88 -5
- abstractcore/providers/mlx_provider.py +33 -1
- abstractcore/providers/ollama_provider.py +37 -3
- abstractcore/providers/openai_provider.py +18 -1
- abstractcore/server/app.py +1390 -104
- abstractcore/tools/common_tools.py +12 -8
- abstractcore/utils/__init__.py +9 -5
- abstractcore/utils/cli.py +199 -17
- abstractcore/utils/message_preprocessor.py +182 -0
- abstractcore/utils/structured_logging.py +117 -16
- abstractcore/utils/version.py +1 -1
- {abstractcore-2.4.2.dist-info → abstractcore-2.4.4.dist-info}/METADATA +214 -20
- {abstractcore-2.4.2.dist-info → abstractcore-2.4.4.dist-info}/RECORD +34 -27
- {abstractcore-2.4.2.dist-info → abstractcore-2.4.4.dist-info}/entry_points.txt +1 -0
- {abstractcore-2.4.2.dist-info → abstractcore-2.4.4.dist-info}/WHEEL +0 -0
- {abstractcore-2.4.2.dist-info → abstractcore-2.4.4.dist-info}/licenses/LICENSE +0 -0
- {abstractcore-2.4.2.dist-info → abstractcore-2.4.4.dist-info}/top_level.txt +0 -0
|
@@ -25,6 +25,94 @@ try:
|
|
|
25
25
|
except ImportError:
|
|
26
26
|
STRUCTLOG_AVAILABLE = False
|
|
27
27
|
|
|
28
|
+
try:
|
|
29
|
+
import colorama
|
|
30
|
+
from colorama import Fore, Style
|
|
31
|
+
COLORAMA_AVAILABLE = True
|
|
32
|
+
# Initialize colorama for cross-platform colored output
|
|
33
|
+
colorama.init(autoreset=True)
|
|
34
|
+
except ImportError:
|
|
35
|
+
COLORAMA_AVAILABLE = False
|
|
36
|
+
# Fallback empty classes if colorama not available
|
|
37
|
+
class Fore:
|
|
38
|
+
RED = YELLOW = GREEN = CYAN = BLUE = MAGENTA = WHITE = RESET = ""
|
|
39
|
+
class Style:
|
|
40
|
+
BRIGHT = DIM = RESET_ALL = ""
|
|
41
|
+
|
|
42
|
+
# Import configuration manager
|
|
43
|
+
def _get_config_defaults():
|
|
44
|
+
"""Get configuration defaults from centralized config system."""
|
|
45
|
+
try:
|
|
46
|
+
from ..config import get_config_manager
|
|
47
|
+
config_manager = get_config_manager()
|
|
48
|
+
logging_config = config_manager.config.logging
|
|
49
|
+
|
|
50
|
+
# Convert string levels to logging constants
|
|
51
|
+
level_map = {
|
|
52
|
+
"DEBUG": logging.DEBUG,
|
|
53
|
+
"INFO": logging.INFO,
|
|
54
|
+
"WARNING": logging.WARNING,
|
|
55
|
+
"ERROR": logging.ERROR,
|
|
56
|
+
"CRITICAL": logging.CRITICAL,
|
|
57
|
+
"NONE": logging.CRITICAL + 10 # Higher than CRITICAL to effectively disable logging
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
console_level = level_map.get(logging_config.console_level, logging.WARNING)
|
|
61
|
+
file_level = level_map.get(logging_config.file_level, logging.DEBUG)
|
|
62
|
+
|
|
63
|
+
# Use log_base_dir if file logging enabled
|
|
64
|
+
log_dir = None
|
|
65
|
+
if logging_config.file_logging_enabled and logging_config.log_base_dir:
|
|
66
|
+
# Expand user home directory
|
|
67
|
+
log_dir = str(Path(logging_config.log_base_dir).expanduser())
|
|
68
|
+
|
|
69
|
+
return {
|
|
70
|
+
'console_level': console_level,
|
|
71
|
+
'file_level': file_level,
|
|
72
|
+
'log_dir': log_dir,
|
|
73
|
+
'verbatim_enabled': logging_config.verbatim_enabled,
|
|
74
|
+
'console_json': logging_config.console_json,
|
|
75
|
+
'file_json': logging_config.file_json
|
|
76
|
+
}
|
|
77
|
+
except Exception:
|
|
78
|
+
# Fallback to hardcoded defaults if config unavailable
|
|
79
|
+
return {
|
|
80
|
+
'console_level': logging.WARNING,
|
|
81
|
+
'file_level': logging.DEBUG,
|
|
82
|
+
'log_dir': None,
|
|
83
|
+
'verbatim_enabled': True,
|
|
84
|
+
'console_json': False,
|
|
85
|
+
'file_json': True
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
# Color mapping for log levels
|
|
89
|
+
LOG_LEVEL_COLORS = {
|
|
90
|
+
'DEBUG': Fore.CYAN + Style.DIM, # Cyan, dimmed (less prominent)
|
|
91
|
+
'INFO': Fore.GREEN, # Green (informational, good)
|
|
92
|
+
'WARNING': Fore.YELLOW + Style.BRIGHT, # Bright yellow (attention)
|
|
93
|
+
'ERROR': Fore.RED, # Red (error)
|
|
94
|
+
'CRITICAL': Fore.RED + Style.BRIGHT # Bright red (critical)
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
class ColoredFormatter(logging.Formatter):
|
|
98
|
+
"""Custom formatter that adds colors to log levels."""
|
|
99
|
+
|
|
100
|
+
def format(self, record):
|
|
101
|
+
# Get the original formatted message
|
|
102
|
+
formatted_message = super().format(record)
|
|
103
|
+
|
|
104
|
+
# Only add colors if colorama is available and we're outputting to a terminal
|
|
105
|
+
if COLORAMA_AVAILABLE and hasattr(sys.stdout, 'isatty') and sys.stdout.isatty():
|
|
106
|
+
# Get color for this level
|
|
107
|
+
level_color = LOG_LEVEL_COLORS.get(record.levelname, '')
|
|
108
|
+
|
|
109
|
+
if level_color:
|
|
110
|
+
# Replace the level name with colored version
|
|
111
|
+
colored_level = f"{level_color}[{record.levelname}]{Style.RESET_ALL}"
|
|
112
|
+
formatted_message = formatted_message.replace(f"[{record.levelname}]", colored_level)
|
|
113
|
+
|
|
114
|
+
return formatted_message
|
|
115
|
+
|
|
28
116
|
# Global configuration
|
|
29
117
|
class LogConfig:
|
|
30
118
|
"""Global logging configuration singleton."""
|
|
@@ -40,15 +128,19 @@ class LogConfig:
|
|
|
40
128
|
if self._initialized:
|
|
41
129
|
return
|
|
42
130
|
|
|
43
|
-
#
|
|
44
|
-
|
|
45
|
-
self.
|
|
46
|
-
self.
|
|
47
|
-
self.
|
|
48
|
-
self.
|
|
49
|
-
self.
|
|
131
|
+
# Load configuration from centralized config system
|
|
132
|
+
config_defaults = _get_config_defaults()
|
|
133
|
+
self.console_level = config_defaults['console_level']
|
|
134
|
+
self.file_level = config_defaults['file_level']
|
|
135
|
+
self.log_dir = config_defaults['log_dir']
|
|
136
|
+
self.verbatim_enabled = config_defaults['verbatim_enabled']
|
|
137
|
+
self.console_json = config_defaults['console_json']
|
|
138
|
+
self.file_json = config_defaults['file_json']
|
|
50
139
|
self._initialized = True
|
|
51
140
|
|
|
141
|
+
# Setup logging with configuration
|
|
142
|
+
self._setup_structlog()
|
|
143
|
+
|
|
52
144
|
def configure(self,
|
|
53
145
|
console_level: Optional[int] = None,
|
|
54
146
|
file_level: Optional[int] = None,
|
|
@@ -130,7 +222,8 @@ class LogConfig:
|
|
|
130
222
|
if self.console_json:
|
|
131
223
|
console_formatter = logging.Formatter('%(message)s')
|
|
132
224
|
else:
|
|
133
|
-
|
|
225
|
+
# Use colored formatter for better visual distinction
|
|
226
|
+
console_formatter = ColoredFormatter(
|
|
134
227
|
'%(asctime)s [%(levelname)s] %(name)s: %(message)s',
|
|
135
228
|
datefmt='%H:%M:%S'
|
|
136
229
|
)
|
|
@@ -140,7 +233,9 @@ class LogConfig:
|
|
|
140
233
|
# File handler
|
|
141
234
|
if self.log_dir and self.file_level is not None:
|
|
142
235
|
timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
|
|
143
|
-
|
|
236
|
+
log_dir_expanded = Path(self.log_dir).expanduser()
|
|
237
|
+
log_dir_expanded.mkdir(parents=True, exist_ok=True)
|
|
238
|
+
log_file = log_dir_expanded / f"abstractcore_{timestamp}.log"
|
|
144
239
|
|
|
145
240
|
file_handler = logging.FileHandler(log_file)
|
|
146
241
|
file_handler.setLevel(self.file_level)
|
|
@@ -154,13 +249,19 @@ class LogConfig:
|
|
|
154
249
|
file_handler.setFormatter(file_formatter)
|
|
155
250
|
root_logger.addHandler(file_handler)
|
|
156
251
|
|
|
157
|
-
# Set root logger level to the most verbose level
|
|
158
|
-
if
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
252
|
+
# Set root logger level to the most verbose level of enabled handlers
|
|
253
|
+
# Only consider file_level if file logging is actually enabled (log_dir is set)
|
|
254
|
+
effective_levels = []
|
|
255
|
+
if self.console_level is not None:
|
|
256
|
+
effective_levels.append(self.console_level)
|
|
257
|
+
if self.file_level is not None and self.log_dir:
|
|
258
|
+
effective_levels.append(self.file_level)
|
|
259
|
+
|
|
260
|
+
if effective_levels:
|
|
261
|
+
root_logger.setLevel(min(effective_levels))
|
|
262
|
+
else:
|
|
263
|
+
# No handlers enabled, set to WARNING as a safe default
|
|
264
|
+
root_logger.setLevel(logging.WARNING)
|
|
164
265
|
|
|
165
266
|
|
|
166
267
|
# Global config instance
|
abstractcore/utils/version.py
CHANGED
|
@@ -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.
|
|
14
|
+
__version__ = "2.4.4"
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: abstractcore
|
|
3
|
-
Version: 2.4.
|
|
3
|
+
Version: 2.4.4
|
|
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>
|
|
@@ -46,6 +46,11 @@ Provides-Extra: embeddings
|
|
|
46
46
|
Requires-Dist: sentence-transformers<4.0.0,>=2.7.0; extra == "embeddings"
|
|
47
47
|
Requires-Dist: numpy<2.0.0,>=1.20.0; extra == "embeddings"
|
|
48
48
|
Provides-Extra: processing
|
|
49
|
+
Provides-Extra: media
|
|
50
|
+
Requires-Dist: Pillow<12.0.0,>=10.0.0; extra == "media"
|
|
51
|
+
Requires-Dist: pymupdf4llm<1.0.0,>=0.0.20; extra == "media"
|
|
52
|
+
Requires-Dist: unstructured[office]<1.0.0,>=0.10.0; extra == "media"
|
|
53
|
+
Requires-Dist: pandas<3.0.0,>=1.0.0; extra == "media"
|
|
49
54
|
Provides-Extra: api-providers
|
|
50
55
|
Requires-Dist: abstractcore[anthropic,openai]; extra == "api-providers"
|
|
51
56
|
Provides-Extra: local-providers
|
|
@@ -55,9 +60,9 @@ Requires-Dist: abstractcore[huggingface]; extra == "heavy-providers"
|
|
|
55
60
|
Provides-Extra: all-providers
|
|
56
61
|
Requires-Dist: abstractcore[anthropic,embeddings,huggingface,lmstudio,mlx,ollama,openai]; extra == "all-providers"
|
|
57
62
|
Provides-Extra: all
|
|
58
|
-
Requires-Dist: abstractcore[anthropic,dev,docs,embeddings,huggingface,lmstudio,mlx,ollama,openai,processing,server,test]; extra == "all"
|
|
63
|
+
Requires-Dist: abstractcore[anthropic,dev,docs,embeddings,huggingface,lmstudio,media,mlx,ollama,openai,processing,server,test]; extra == "all"
|
|
59
64
|
Provides-Extra: lightweight
|
|
60
|
-
Requires-Dist: abstractcore[anthropic,embeddings,lmstudio,ollama,openai,processing,server]; extra == "lightweight"
|
|
65
|
+
Requires-Dist: abstractcore[anthropic,embeddings,lmstudio,media,ollama,openai,processing,server]; extra == "lightweight"
|
|
61
66
|
Provides-Extra: dev
|
|
62
67
|
Requires-Dist: pytest>=7.0.0; extra == "dev"
|
|
63
68
|
Requires-Dist: pytest-asyncio>=0.21.0; extra == "dev"
|
|
@@ -89,6 +94,11 @@ Dynamic: license-file
|
|
|
89
94
|
|
|
90
95
|
# AbstractCore
|
|
91
96
|
|
|
97
|
+
[](https://pypi.org/project/abstractcore/)
|
|
98
|
+
[](https://pypi.org/project/abstractcore/)
|
|
99
|
+
[](https://github.com/lpalbou/abstractcore/blob/main/LICENSE)
|
|
100
|
+
[](https://github.com/lpalbou/abstractcore/stargazers)
|
|
101
|
+
|
|
92
102
|
A unified Python library for interaction with multiple Large Language Model (LLM) providers.
|
|
93
103
|
|
|
94
104
|
**Write once, run everywhere.**
|
|
@@ -153,15 +163,68 @@ loaded_session = BasicSession.load('conversation.json', provider=llm)
|
|
|
153
163
|
|
|
154
164
|
[Learn more about Session](docs/session.md)
|
|
155
165
|
|
|
166
|
+
### Media Handling
|
|
167
|
+
|
|
168
|
+
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.
|
|
169
|
+
|
|
170
|
+
```python
|
|
171
|
+
from abstractcore import create_llm
|
|
172
|
+
|
|
173
|
+
# Vision analysis - works with any vision model
|
|
174
|
+
# Images automatically processed at maximum supported resolution
|
|
175
|
+
llm = create_llm("openai", model="gpt-4o")
|
|
176
|
+
response = llm.generate(
|
|
177
|
+
"What's in this image?",
|
|
178
|
+
media=["photo.jpg"] # Auto-resized to model's maximum capability
|
|
179
|
+
)
|
|
180
|
+
|
|
181
|
+
# Document analysis - works with any model
|
|
182
|
+
llm = create_llm("anthropic", model="claude-3.5-sonnet")
|
|
183
|
+
response = llm.generate(
|
|
184
|
+
"Summarize this research paper",
|
|
185
|
+
media=["research_paper.pdf"]
|
|
186
|
+
)
|
|
187
|
+
|
|
188
|
+
# Multiple files - mix images, PDFs, spreadsheets
|
|
189
|
+
response = llm.generate(
|
|
190
|
+
"Analyze these business documents",
|
|
191
|
+
media=["report.pdf", "chart.png", "data.xlsx"]
|
|
192
|
+
)
|
|
193
|
+
|
|
194
|
+
# Same code works with local models
|
|
195
|
+
llm = create_llm("ollama", model="qwen3-vl:8b")
|
|
196
|
+
response = llm.generate(
|
|
197
|
+
"Describe this screenshot",
|
|
198
|
+
media=["screenshot.png"] # Auto-optimized for qwen3-vl
|
|
199
|
+
)
|
|
200
|
+
```
|
|
201
|
+
|
|
202
|
+
**Key Features:**
|
|
203
|
+
- **Smart Resolution**: Automatically uses maximum resolution supported by each model
|
|
204
|
+
- **Format Support**: PNG, JPEG, GIF, WEBP, BMP, TIFF images; PDF, TXT, MD, CSV, TSV, JSON documents
|
|
205
|
+
- **Office Documents**: DOCX, XLSX, PPT (with `pip install abstractcore[all]`)
|
|
206
|
+
- **Vision Optimization**: Model-specific image processing for best vision results
|
|
207
|
+
|
|
208
|
+
**Provider compatibility:**
|
|
209
|
+
- **High-resolution vision**: GPT-4o (up to 4096x4096), Claude 3.5 Sonnet (up to 1568x1568)
|
|
210
|
+
- **Local models**: qwen3-vl (up to 3584x3584), gemma3:4b, llama3.2-vision
|
|
211
|
+
- **All models**: Automatic text extraction for non-vision models
|
|
212
|
+
|
|
213
|
+
[Learn more about Media Handling](docs/media-handling-system.md)
|
|
214
|
+
|
|
156
215
|
## Key Features
|
|
157
216
|
|
|
158
217
|
- **Provider Agnostic**: Seamlessly switch between OpenAI, Anthropic, Ollama, LMStudio, MLX, HuggingFace
|
|
218
|
+
- **Centralized Configuration**: Global defaults and app-specific preferences at `~/.abstractcore/config/abstractcore.json`
|
|
219
|
+
- **Intelligent Media Handling**: Upload images, PDFs, and documents with automatic maximum resolution optimization
|
|
220
|
+
- **Vision Model Support**: Smart image processing at each model's maximum capability for best results
|
|
221
|
+
- **Document Processing**: Advanced PDF extraction (PyMuPDF4LLM), Office documents (DOCX/XLSX/PPT), CSV/TSV analysis
|
|
159
222
|
- **Unified Tools**: Consistent tool calling across all providers
|
|
160
223
|
- **Session Management**: Persistent conversations with metadata, analytics, and complete serialization
|
|
161
224
|
- **Structured Responses**: Clean, predictable output formats with Pydantic
|
|
162
225
|
- **Streaming Support**: Real-time token generation for interactive experiences
|
|
163
226
|
- **Embeddings**: Built-in support for semantic search and RAG applications
|
|
164
|
-
- **Universal Server**: Optional OpenAI-compatible API server
|
|
227
|
+
- **Universal Server**: Optional OpenAI-compatible API server with `/v1/responses` endpoint
|
|
165
228
|
|
|
166
229
|
## Supported Providers
|
|
167
230
|
|
|
@@ -199,12 +262,15 @@ response = client.chat.completions.create(
|
|
|
199
262
|
```
|
|
200
263
|
|
|
201
264
|
**Server Features:**
|
|
202
|
-
- OpenAI-compatible REST endpoints (`/v1/chat/completions`, `/v1/embeddings`,
|
|
265
|
+
- OpenAI-compatible REST endpoints (`/v1/chat/completions`, `/v1/embeddings`, `/v1/responses`)
|
|
266
|
+
- **NEW in v2.5.0**: OpenAI Responses API (`/v1/responses`) with native `input_file` support
|
|
203
267
|
- Multi-provider support through one HTTP API
|
|
268
|
+
- Comprehensive media processing (images, PDFs, Office documents, CSV/TSV)
|
|
204
269
|
- Agentic CLI integration (Codex, Crush, Gemini CLI)
|
|
205
|
-
- Streaming responses
|
|
270
|
+
- Streaming responses with optional opt-in
|
|
206
271
|
- Tool call format conversion
|
|
207
|
-
-
|
|
272
|
+
- Enhanced debug logging with `--debug` flag
|
|
273
|
+
- Interactive API docs at `/docs` (Swagger UI)
|
|
208
274
|
|
|
209
275
|
**When to use the server:**
|
|
210
276
|
- Integrating with existing OpenAI-compatible tools
|
|
@@ -365,6 +431,72 @@ Each application has comprehensive documentation with examples and advanced usag
|
|
|
365
431
|
- Integration with shell scripts and automation
|
|
366
432
|
- Standardized text processing tasks
|
|
367
433
|
|
|
434
|
+
## Configuration
|
|
435
|
+
|
|
436
|
+
AbstractCore provides a **centralized configuration system** that manages default models, cache directories, and logging settings from a single location. This eliminates the need to specify `--provider` and `--model` parameters repeatedly.
|
|
437
|
+
|
|
438
|
+
### Quick Setup
|
|
439
|
+
|
|
440
|
+
```bash
|
|
441
|
+
# Check current configuration (shows how to change each setting)
|
|
442
|
+
abstractcore --status
|
|
443
|
+
|
|
444
|
+
# Set defaults for all applications
|
|
445
|
+
abstractcore --set-global-default ollama/llama3:8b
|
|
446
|
+
|
|
447
|
+
# Or configure specific applications (examples of customization)
|
|
448
|
+
abstractcore --set-app-default summarizer openai gpt-4o-mini
|
|
449
|
+
abstractcore --set-app-default extractor ollama qwen3:4b-instruct
|
|
450
|
+
abstractcore --set-app-default judge anthropic claude-3-5-haiku
|
|
451
|
+
|
|
452
|
+
# Configure logging (common examples)
|
|
453
|
+
abstractcore --set-console-log-level WARNING # Reduce console output
|
|
454
|
+
abstractcore --set-console-log-level NONE # Disable console logging
|
|
455
|
+
abstractcore --enable-file-logging # Save logs to files
|
|
456
|
+
abstractcore --enable-debug-logging # Full debug mode
|
|
457
|
+
|
|
458
|
+
# Set API keys as needed
|
|
459
|
+
abstractcore --set-api-key openai sk-your-key-here
|
|
460
|
+
abstractcore --set-api-key anthropic your-anthropic-key
|
|
461
|
+
|
|
462
|
+
# Verify configuration (includes change commands for each setting)
|
|
463
|
+
abstractcore --status
|
|
464
|
+
```
|
|
465
|
+
|
|
466
|
+
### Priority System
|
|
467
|
+
|
|
468
|
+
AbstractCore uses a clear priority system where explicit parameters always override defaults:
|
|
469
|
+
|
|
470
|
+
1. **Explicit parameters** (highest priority): `summarizer doc.txt --provider openai --model gpt-4o-mini`
|
|
471
|
+
2. **App-specific config**: `abstractcore --set-app-default summarizer openai gpt-4o-mini`
|
|
472
|
+
3. **Global config**: `abstractcore --set-global-default openai/gpt-4o-mini`
|
|
473
|
+
4. **Built-in defaults** (lowest priority): `huggingface/unsloth/Qwen3-4B-Instruct-2507-GGUF`
|
|
474
|
+
|
|
475
|
+
### Usage After Configuration
|
|
476
|
+
|
|
477
|
+
Once configured, apps use your defaults automatically:
|
|
478
|
+
|
|
479
|
+
```bash
|
|
480
|
+
# Before configuration (requires explicit parameters)
|
|
481
|
+
summarizer document.pdf --provider openai --model gpt-4o-mini
|
|
482
|
+
|
|
483
|
+
# After configuration (uses configured defaults)
|
|
484
|
+
summarizer document.pdf
|
|
485
|
+
|
|
486
|
+
# Explicit parameters still override when needed
|
|
487
|
+
summarizer document.pdf --provider anthropic --model claude-3-5-sonnet
|
|
488
|
+
```
|
|
489
|
+
|
|
490
|
+
### Configuration Features
|
|
491
|
+
|
|
492
|
+
- **Application defaults**: Different optimal models for each app
|
|
493
|
+
- **Cache directories**: Configurable cache locations for models and data
|
|
494
|
+
- **Logging control**: Package-wide logging levels and debug mode
|
|
495
|
+
- **API key management**: Centralized API key storage
|
|
496
|
+
- **Interactive setup**: `abstractcore --configure` for guided configuration
|
|
497
|
+
|
|
498
|
+
**Complete guide**: [Centralized Configuration](docs/centralized-config.md)
|
|
499
|
+
|
|
368
500
|
## Documentation
|
|
369
501
|
|
|
370
502
|
**📚 Complete Documentation:** [docs/](docs/) - Full documentation index and navigation guide
|
|
@@ -376,6 +508,7 @@ Each application has comprehensive documentation with examples and advanced usag
|
|
|
376
508
|
|
|
377
509
|
### Core Library (Python)
|
|
378
510
|
- **[Python API Reference](docs/api-reference.md)** - Complete Python API documentation
|
|
511
|
+
- **[Media Handling System](docs/media-handling-system.md)** - Images, PDFs, and document processing across all providers
|
|
379
512
|
- **[Session Management](docs/session.md)** - Persistent conversations, serialization, and analytics
|
|
380
513
|
- **[Embeddings Guide](docs/embeddings.md)** - Semantic search, RAG, and vector embeddings
|
|
381
514
|
- **[Code Examples](examples/)** - Working examples for all features
|
|
@@ -401,7 +534,44 @@ for provider in providers:
|
|
|
401
534
|
response = llm.generate("Hello!")
|
|
402
535
|
```
|
|
403
536
|
|
|
404
|
-
### 2.
|
|
537
|
+
### 2. Vision Analysis Across Providers
|
|
538
|
+
|
|
539
|
+
```python
|
|
540
|
+
# Same image analysis works with any vision model
|
|
541
|
+
image_files = ["product_photo.jpg", "user_feedback.png"]
|
|
542
|
+
prompt = "Analyze these product images and suggest improvements"
|
|
543
|
+
|
|
544
|
+
# OpenAI GPT-4o
|
|
545
|
+
openai_llm = create_llm("openai", model="gpt-4o")
|
|
546
|
+
openai_analysis = openai_llm.generate(prompt, media=image_files)
|
|
547
|
+
|
|
548
|
+
# Anthropic Claude
|
|
549
|
+
claude_llm = create_llm("anthropic", model="claude-3.5-sonnet")
|
|
550
|
+
claude_analysis = claude_llm.generate(prompt, media=image_files)
|
|
551
|
+
|
|
552
|
+
# Local model (free)
|
|
553
|
+
local_llm = create_llm("ollama", model="qwen3-vl:8b")
|
|
554
|
+
local_analysis = local_llm.generate(prompt, media=image_files)
|
|
555
|
+
```
|
|
556
|
+
|
|
557
|
+
### 3. Document Processing Pipeline
|
|
558
|
+
|
|
559
|
+
```python
|
|
560
|
+
# Universal document analysis
|
|
561
|
+
documents = ["contract.pdf", "financial_data.xlsx", "presentation.ppt"]
|
|
562
|
+
analysis_prompt = "Extract key information and identify potential risks"
|
|
563
|
+
|
|
564
|
+
# Works with any provider
|
|
565
|
+
llm = create_llm("anthropic", model="claude-3.5-sonnet")
|
|
566
|
+
response = llm.generate(analysis_prompt, media=documents)
|
|
567
|
+
|
|
568
|
+
# Automatic format handling:
|
|
569
|
+
# - PDF: Advanced text extraction with PyMuPDF4LLM
|
|
570
|
+
# - Excel: Table parsing with pandas
|
|
571
|
+
# - PowerPoint: Slide content extraction with unstructured
|
|
572
|
+
```
|
|
573
|
+
|
|
574
|
+
### 4. Local Development, Cloud Production
|
|
405
575
|
|
|
406
576
|
```python
|
|
407
577
|
# Development (free, local)
|
|
@@ -411,7 +581,7 @@ llm_dev = create_llm("ollama", model="qwen3:4b-instruct-2507-q4_K_M")
|
|
|
411
581
|
llm_prod = create_llm("openai", model="gpt-4o-mini")
|
|
412
582
|
```
|
|
413
583
|
|
|
414
|
-
###
|
|
584
|
+
### 5. Embeddings & RAG
|
|
415
585
|
|
|
416
586
|
```python
|
|
417
587
|
from abstractcore.embeddings import EmbeddingManager
|
|
@@ -431,7 +601,7 @@ similarity = embedder.compute_similarity(query, docs[0])
|
|
|
431
601
|
|
|
432
602
|
[Learn more about Embeddings](docs/embeddings.md)
|
|
433
603
|
|
|
434
|
-
###
|
|
604
|
+
### 6. Structured Output
|
|
435
605
|
|
|
436
606
|
```python
|
|
437
607
|
from pydantic import BaseModel
|
|
@@ -449,7 +619,7 @@ review = llm.generate(
|
|
|
449
619
|
print(f"{review.title}: {review.rating}/5")
|
|
450
620
|
```
|
|
451
621
|
|
|
452
|
-
###
|
|
622
|
+
### 7. Universal API Server
|
|
453
623
|
|
|
454
624
|
```bash
|
|
455
625
|
# Start server once
|
|
@@ -466,14 +636,16 @@ curl -X POST http://localhost:8000/v1/chat/completions \
|
|
|
466
636
|
|
|
467
637
|
## Why AbstractCore?
|
|
468
638
|
|
|
469
|
-
- **Unified Interface**: One API for all LLM providers
|
|
470
|
-
- **
|
|
471
|
-
- **
|
|
472
|
-
- **
|
|
473
|
-
- **
|
|
474
|
-
- **
|
|
475
|
-
- **
|
|
476
|
-
- **
|
|
639
|
+
- **Unified Interface**: One API for all LLM providers
|
|
640
|
+
- **Multimodal Support**: Upload images, PDFs, and documents across all providers
|
|
641
|
+
- **Vision Models**: Seamless integration with GPT-4o, Claude Vision, qwen3-vl, and more
|
|
642
|
+
- **Production Ready**: Robust error handling, retries, timeouts
|
|
643
|
+
- **Type Safe**: Full Pydantic integration for structured outputs
|
|
644
|
+
- **Local & Cloud**: Run models locally or use cloud APIs
|
|
645
|
+
- **Tool Calling**: Consistent function calling across providers
|
|
646
|
+
- **Streaming**: Real-time responses for interactive applications
|
|
647
|
+
- **Embeddings**: Built-in vector embeddings for RAG
|
|
648
|
+
- **Server Mode**: Optional OpenAI-compatible API server
|
|
477
649
|
- **Well Documented**: Comprehensive guides and examples
|
|
478
650
|
|
|
479
651
|
## Installation Options
|
|
@@ -482,6 +654,9 @@ curl -X POST http://localhost:8000/v1/chat/completions \
|
|
|
482
654
|
# Minimal core
|
|
483
655
|
pip install abstractcore
|
|
484
656
|
|
|
657
|
+
# With media handling (images, PDFs, documents)
|
|
658
|
+
pip install abstractcore[media]
|
|
659
|
+
|
|
485
660
|
# With specific providers
|
|
486
661
|
pip install abstractcore[openai]
|
|
487
662
|
pip install abstractcore[anthropic]
|
|
@@ -493,10 +668,25 @@ pip install abstractcore[server]
|
|
|
493
668
|
# With embeddings
|
|
494
669
|
pip install abstractcore[embeddings]
|
|
495
670
|
|
|
496
|
-
# Everything
|
|
671
|
+
# Everything (recommended)
|
|
497
672
|
pip install abstractcore[all]
|
|
498
673
|
```
|
|
499
674
|
|
|
675
|
+
**Media processing extras:**
|
|
676
|
+
```bash
|
|
677
|
+
# For advanced PDF processing
|
|
678
|
+
pip install pymupdf4llm
|
|
679
|
+
|
|
680
|
+
# For Office documents (DOCX, XLSX, PPT)
|
|
681
|
+
pip install unstructured
|
|
682
|
+
|
|
683
|
+
# For image optimization
|
|
684
|
+
pip install pillow
|
|
685
|
+
|
|
686
|
+
# For data processing (CSV, Excel)
|
|
687
|
+
pip install pandas
|
|
688
|
+
```
|
|
689
|
+
|
|
500
690
|
## Testing Status
|
|
501
691
|
|
|
502
692
|
All tests passing as of October 12th, 2025.
|
|
@@ -519,6 +709,10 @@ All tests passing as of October 12th, 2025.
|
|
|
519
709
|
- **[🐛 Issues](https://github.com/lpalbou/AbstractCore/issues)** - Report bugs
|
|
520
710
|
- **[💬 Discussions](https://github.com/lpalbou/AbstractCore/discussions)** - Get help
|
|
521
711
|
|
|
712
|
+
## Contact
|
|
713
|
+
**Maintainer:** Laurent-Philippe Albou
|
|
714
|
+
📧 Email: [contact@abstractcore.ai](mailto:contact@abstractcore.ai)
|
|
715
|
+
|
|
522
716
|
## Contributing
|
|
523
717
|
|
|
524
718
|
We welcome contributions! See [CONTRIBUTING.md](CONTRIBUTING.md) for guidelines.
|
|
@@ -1,65 +1,72 @@
|
|
|
1
1
|
abstractcore/__init__.py,sha256=7ucTDQXINslx23n-vaFOeFzRAYi76Enqak2S3rjaZLU,1861
|
|
2
2
|
abstractcore/apps/__init__.py,sha256=sgNOv3lYyOWNBC-w6GnRN6aILGCbdkQtNcuQdJz5ghE,31
|
|
3
3
|
abstractcore/apps/__main__.py,sha256=041daYkoIE1VLEO19IZC5nNIDOQZWNgpB7ogJ3SOlsE,1585
|
|
4
|
+
abstractcore/apps/app_config_utils.py,sha256=GygjtkianBktRvirHya1KbXuB2r5OUDJM6ilvybQWvk,875
|
|
4
5
|
abstractcore/apps/extractor.py,sha256=OfiqB9l_alH9xCGb6zOD__QJkDjdKOlLZngriVgmn7c,23749
|
|
5
6
|
abstractcore/apps/judge.py,sha256=nOgxvn-BbhNY6xU9AlTeD1yidTh73AiVlSN7hQCVE2M,23169
|
|
6
|
-
abstractcore/apps/summarizer.py,sha256=
|
|
7
|
+
abstractcore/apps/summarizer.py,sha256=9aD6KH21w-tv_wGp9MaO2uyJuaU71OemW7KpqrG5t6w,14669
|
|
7
8
|
abstractcore/architectures/__init__.py,sha256=-4JucAM7JkMWShWKkePoclxrUHRKgaG36UTguJihE0U,1046
|
|
8
|
-
abstractcore/architectures/detection.py,sha256=
|
|
9
|
+
abstractcore/architectures/detection.py,sha256=Cxap1pL6qOJjyY22Vc4hzbLALTuuBisPT5UaMotousk,10025
|
|
9
10
|
abstractcore/architectures/enums.py,sha256=9vIv2vDBEKhxwzwH9iaSAyf-iVj3p8y9loMeN_mYTJ8,3821
|
|
10
|
-
abstractcore/assets/architecture_formats.json,sha256=
|
|
11
|
-
abstractcore/assets/model_capabilities.json,sha256=
|
|
11
|
+
abstractcore/assets/architecture_formats.json,sha256=CIf6SaR_IJs1D7Uvd1K3zWngIXJ_yq3DM_IE3wnpCHY,16076
|
|
12
|
+
abstractcore/assets/model_capabilities.json,sha256=iUkDiljyZUZzPlpYCOFgStXyc6e7dvOfReYQ0HFrX9Q,49703
|
|
12
13
|
abstractcore/assets/session_schema.json,sha256=b6HTAWxRVlVhAzA7FqaKpunK1yO6jilBOsD5sQkqJTo,10580
|
|
13
14
|
abstractcore/core/__init__.py,sha256=2h-86U4QkCQ4gzZ4iRusSTMlkODiUS6tKjZHiEXz6rM,684
|
|
14
15
|
abstractcore/core/enums.py,sha256=BhkVnHC-X1_377JDmqd-2mnem9GdBLqixWlYzlP_FJU,695
|
|
15
16
|
abstractcore/core/factory.py,sha256=UdrNwQAvifvFS3LMjF5KO87m-2n1bJBryTs9pvesYcI,2804
|
|
16
|
-
abstractcore/core/interface.py,sha256=
|
|
17
|
+
abstractcore/core/interface.py,sha256=XTvtP1YY_2dSlSdKWkkDK54VtEeUt97zIDR1tXTtn8Q,13876
|
|
17
18
|
abstractcore/core/retry.py,sha256=wNlUAxfmvdO_uVWb4iqkhTqd7O1oRwXxqvVQaLXQOw0,14538
|
|
18
|
-
abstractcore/core/session.py,sha256=
|
|
19
|
+
abstractcore/core/session.py,sha256=iU_fU7f7E6HxwkV97QnSMJSF6rOIuJyT6sQGf547S6s,35347
|
|
19
20
|
abstractcore/core/types.py,sha256=KT9Gf9ei4t0QnWBH72fFa8vR7UZSKI-CJyQjU9ynE8g,3642
|
|
20
21
|
abstractcore/embeddings/__init__.py,sha256=hR3xZyqcRm4c2pq1dIa5lxj_-Bk70Zad802JQN4joWo,637
|
|
21
|
-
abstractcore/embeddings/manager.py,sha256=
|
|
22
|
+
abstractcore/embeddings/manager.py,sha256=uFVbRPHx_R-kVMVA7N7_7EzeUmCJCeN9Dv0EV8Jko24,52245
|
|
22
23
|
abstractcore/embeddings/models.py,sha256=bsPAzL6gv57AVii8O15PT0kxfwRkOml3f3njJN4UDi4,4874
|
|
23
24
|
abstractcore/events/__init__.py,sha256=UtbdTOeL05kvi7YP91yo4OEqs5UAbKylBvOOEkrUL5E,11065
|
|
24
25
|
abstractcore/exceptions/__init__.py,sha256=h6y3sdZR6uFMh0iq7z85DfJi01zGQvjVOm1W7l86iVQ,3224
|
|
25
|
-
abstractcore/media/__init__.py,sha256=
|
|
26
|
+
abstractcore/media/__init__.py,sha256=94k22PRXInaXFlxU7p06IRbyjmOkSlCITDm0gb8d9AI,3202
|
|
27
|
+
abstractcore/media/auto_handler.py,sha256=R3EhifSlGSJ_2oftQ7BdD7nQBMGePHOubuXkqHmcHHQ,13478
|
|
28
|
+
abstractcore/media/base.py,sha256=vWdxscqTGTvd3oc4IzzsBTWhUrznWcqM7M_sFyq6-eE,15971
|
|
29
|
+
abstractcore/media/capabilities.py,sha256=qqKvXGkUT-FNnbFS-EYx8KCT9SZOovO2h4N7ucrHgBA,12844
|
|
30
|
+
abstractcore/media/types.py,sha256=jG-g_2_gzl8eOgEalk9x3Ikhni9GoGfoRjkZWaBhV30,10165
|
|
31
|
+
abstractcore/media/vision_fallback.py,sha256=XcEV5T9ekqd4DRBrhJvxgX5j_puxSlofvuUIfQc2vmg,10629
|
|
26
32
|
abstractcore/processing/__init__.py,sha256=t6hiakQjcZROT4pw9ZFt2q6fF3vf5VpdMKG2EWlsFd8,540
|
|
27
33
|
abstractcore/processing/basic_extractor.py,sha256=3x-3BdIHgLvqLnLF6K1-P4qVaLIpAnNIIutaJi7lDQM,49832
|
|
28
34
|
abstractcore/processing/basic_judge.py,sha256=tKWJrg_tY4vCHzWgXxz0ZjgLXBYYfpMcpG7vl03hJcM,32218
|
|
29
35
|
abstractcore/processing/basic_summarizer.py,sha256=XHNxMQ_8aLStTeUo6_2JaThlct12Htpz7ORmm0iuJsg,25495
|
|
30
36
|
abstractcore/providers/__init__.py,sha256=t8Kp4flH5GvZEC6dx-iYJSPeSxMODa2spXb8MqtlPy4,1282
|
|
31
|
-
abstractcore/providers/anthropic_provider.py,sha256=
|
|
32
|
-
abstractcore/providers/base.py,sha256=
|
|
33
|
-
abstractcore/providers/huggingface_provider.py,sha256=
|
|
34
|
-
abstractcore/providers/lmstudio_provider.py,sha256=
|
|
35
|
-
abstractcore/providers/mlx_provider.py,sha256=
|
|
37
|
+
abstractcore/providers/anthropic_provider.py,sha256=tcOrARLd1kA4vRkH7MCgy99YIGVaegdCd3-Z8UaKP3Q,20705
|
|
38
|
+
abstractcore/providers/base.py,sha256=5YR64kqTYiCvWtIUBul5QfO0XRZr6_Aiho4atpDOh0o,50579
|
|
39
|
+
abstractcore/providers/huggingface_provider.py,sha256=mJGfi1lgsvjV3Lj4q7KCQZhQqw_o23af40i5WLg150o,47789
|
|
40
|
+
abstractcore/providers/lmstudio_provider.py,sha256=oPL_Y4gkJMAniecdWQVaDi7WozCZumSRs0lE7uFgvQk,20406
|
|
41
|
+
abstractcore/providers/mlx_provider.py,sha256=61i5VhpNw_QlhOwPcEcryaGbI45aYyL9q15TrpinIgs,17427
|
|
36
42
|
abstractcore/providers/mock_provider.py,sha256=tIjA57Hlwu3vNODOZShNn0tY9HWvz1p4z-HyD_bsvbo,5741
|
|
37
|
-
abstractcore/providers/ollama_provider.py,sha256=
|
|
38
|
-
abstractcore/providers/openai_provider.py,sha256=
|
|
43
|
+
abstractcore/providers/ollama_provider.py,sha256=O77Nzx0erQw8D5TlyVaunIOjluaRwi8bgYVO95qK0L4,21129
|
|
44
|
+
abstractcore/providers/openai_provider.py,sha256=gHurjXwwKvKQtkK5cqwokW_DUTY9_bsfNm06RPvQ39g,22683
|
|
39
45
|
abstractcore/providers/registry.py,sha256=c0hxp9RRa-uipGotaAu48fHXc_HGlLcOxC1k763mzhU,16596
|
|
40
46
|
abstractcore/providers/streaming.py,sha256=VnffBV_CU9SAKzghL154OoFyEdDsiLwUNXPahyU41Bw,31342
|
|
41
47
|
abstractcore/server/__init__.py,sha256=1DSAz_YhQtnKv7sNi5TMQV8GFujctDOabgvAdilQE0o,249
|
|
42
|
-
abstractcore/server/app.py,sha256=
|
|
48
|
+
abstractcore/server/app.py,sha256=2ChRxdpMyGVCjsQPWWpPNtqdtfIIhbpF3uLuTCiF6lo,96629
|
|
43
49
|
abstractcore/structured/__init__.py,sha256=VXRQHGcm-iaYnLOBPin2kyhvhhQA0kaGt_pcNDGsE_8,339
|
|
44
50
|
abstractcore/structured/handler.py,sha256=Vb15smiR81JGDXX2RLkY2Exuj67J7a6C-xwVrZoXp0I,17134
|
|
45
51
|
abstractcore/structured/retry.py,sha256=BN_PvrWybyU1clMy2cult1-TVxFSMaVqiCPmmXvA5aI,3805
|
|
46
52
|
abstractcore/tools/__init__.py,sha256=oh6vG0RdM1lqUtOp95mLrTsWLh9VmhJf5_FVjGIP5_M,2259
|
|
47
|
-
abstractcore/tools/common_tools.py,sha256=
|
|
53
|
+
abstractcore/tools/common_tools.py,sha256=jRVvu-TQbmXBOZHn00zEZb44nenaXVtdemhKmRmt1YY,64496
|
|
48
54
|
abstractcore/tools/core.py,sha256=lUUGihyceiRYlKUFvEMig9jWFF563d574mSDbYYD3fM,4777
|
|
49
55
|
abstractcore/tools/handler.py,sha256=GmDenXAJkhceWSGlhvuF90aMb2301tRTh6WxGwBQifc,12022
|
|
50
56
|
abstractcore/tools/parser.py,sha256=1r5nmEEp1Rid3JU6ct-s3lP-eCln67fvXG5HCjqiRew,27740
|
|
51
57
|
abstractcore/tools/registry.py,sha256=cN3nbPEK6L2vAd9740MIFf2fitW_4WHpQfK4KvQjnT0,9059
|
|
52
58
|
abstractcore/tools/syntax_rewriter.py,sha256=c3NSTvUF3S3ho5Cwjp7GJJdibeYAI6k3iaBwhKcpTfo,17318
|
|
53
59
|
abstractcore/tools/tag_rewriter.py,sha256=UGFMBj2QKwm12j8JQ6oc2C_N3ZeNqz9Enz4VkEIrS0c,20338
|
|
54
|
-
abstractcore/utils/__init__.py,sha256=
|
|
55
|
-
abstractcore/utils/cli.py,sha256=
|
|
60
|
+
abstractcore/utils/__init__.py,sha256=29mMc3jV_suEPBn7W8Yw_wqcdvFP-083ws5AUFJVM28,676
|
|
61
|
+
abstractcore/utils/cli.py,sha256=btuTIECrBPV4cdoWoE-N1rkzcrq--dhwKbtZTQhvwok,65175
|
|
62
|
+
abstractcore/utils/message_preprocessor.py,sha256=GdHkm6tmrgjm3PwHRSCjIsq1XLkbhy_vDEKEUE7OiKY,6028
|
|
56
63
|
abstractcore/utils/self_fixes.py,sha256=QEDwNTW80iQM4ftfEY3Ghz69F018oKwLM9yeRCYZOvw,5886
|
|
57
|
-
abstractcore/utils/structured_logging.py,sha256=
|
|
64
|
+
abstractcore/utils/structured_logging.py,sha256=Vm-HviSa42G9DJCWmaEv4a0QG3NMsADD3ictLOs4En0,19952
|
|
58
65
|
abstractcore/utils/token_utils.py,sha256=eLwFmJ68p9WMFD_MHLMmeJRW6Oqx_4hKELB8FNQ2Mnk,21097
|
|
59
|
-
abstractcore/utils/version.py,sha256=
|
|
60
|
-
abstractcore-2.4.
|
|
61
|
-
abstractcore-2.4.
|
|
62
|
-
abstractcore-2.4.
|
|
63
|
-
abstractcore-2.4.
|
|
64
|
-
abstractcore-2.4.
|
|
65
|
-
abstractcore-2.4.
|
|
66
|
+
abstractcore/utils/version.py,sha256=ykpU7S-ZbOgwDZo_6zYttC6y8VPe3CuV0anATrFRej8,605
|
|
67
|
+
abstractcore-2.4.4.dist-info/licenses/LICENSE,sha256=PI2v_4HMvd6050uDD_4AY_8PzBnu2asa3RKbdDjowTA,1078
|
|
68
|
+
abstractcore-2.4.4.dist-info/METADATA,sha256=h6Wn0s43Xlng3K0bOw4o1LcT293rVoRPgionXu3kQKg,27596
|
|
69
|
+
abstractcore-2.4.4.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
70
|
+
abstractcore-2.4.4.dist-info/entry_points.txt,sha256=di-rxy4iD6A3j8DmQHeVmXYlncgCJKZGamyjrQXEfcU,357
|
|
71
|
+
abstractcore-2.4.4.dist-info/top_level.txt,sha256=DiNHBI35SIawW3N9Z-z0y6cQYNbXd32pvBkW0RLfScs,13
|
|
72
|
+
abstractcore-2.4.4.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|