abstractcore 2.5.3__tar.gz → 2.6.0__tar.gz
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-2.5.3 → abstractcore-2.6.0}/PKG-INFO +102 -4
- {abstractcore-2.5.3 → abstractcore-2.6.0}/README.md +95 -3
- {abstractcore-2.5.3 → abstractcore-2.6.0}/abstractcore/__init__.py +7 -1
- {abstractcore-2.5.3 → abstractcore-2.6.0}/abstractcore/architectures/detection.py +2 -2
- {abstractcore-2.5.3 → abstractcore-2.6.0}/abstractcore/core/retry.py +2 -2
- {abstractcore-2.5.3 → abstractcore-2.6.0}/abstractcore/core/session.py +132 -1
- abstractcore-2.6.0/abstractcore/download.py +253 -0
- {abstractcore-2.5.3 → abstractcore-2.6.0}/abstractcore/embeddings/manager.py +2 -2
- {abstractcore-2.5.3 → abstractcore-2.6.0}/abstractcore/events/__init__.py +112 -1
- {abstractcore-2.5.3 → abstractcore-2.6.0}/abstractcore/exceptions/__init__.py +49 -2
- {abstractcore-2.5.3 → abstractcore-2.6.0}/abstractcore/media/processors/office_processor.py +2 -2
- {abstractcore-2.5.3 → abstractcore-2.6.0}/abstractcore/media/utils/image_scaler.py +2 -2
- {abstractcore-2.5.3 → abstractcore-2.6.0}/abstractcore/media/vision_fallback.py +2 -2
- {abstractcore-2.5.3 → abstractcore-2.6.0}/abstractcore/providers/anthropic_provider.py +200 -6
- {abstractcore-2.5.3 → abstractcore-2.6.0}/abstractcore/providers/base.py +100 -5
- {abstractcore-2.5.3 → abstractcore-2.6.0}/abstractcore/providers/lmstudio_provider.py +246 -2
- {abstractcore-2.5.3 → abstractcore-2.6.0}/abstractcore/providers/ollama_provider.py +244 -2
- {abstractcore-2.5.3 → abstractcore-2.6.0}/abstractcore/providers/openai_provider.py +258 -6
- {abstractcore-2.5.3 → abstractcore-2.6.0}/abstractcore/providers/streaming.py +2 -2
- {abstractcore-2.5.3 → abstractcore-2.6.0}/abstractcore/tools/common_tools.py +2 -2
- {abstractcore-2.5.3 → abstractcore-2.6.0}/abstractcore/tools/handler.py +2 -2
- {abstractcore-2.5.3 → abstractcore-2.6.0}/abstractcore/tools/parser.py +2 -2
- {abstractcore-2.5.3 → abstractcore-2.6.0}/abstractcore/tools/registry.py +2 -2
- {abstractcore-2.5.3 → abstractcore-2.6.0}/abstractcore/tools/syntax_rewriter.py +2 -2
- {abstractcore-2.5.3 → abstractcore-2.6.0}/abstractcore/tools/tag_rewriter.py +3 -3
- {abstractcore-2.5.3 → abstractcore-2.6.0}/abstractcore/utils/self_fixes.py +2 -2
- {abstractcore-2.5.3 → abstractcore-2.6.0}/abstractcore/utils/version.py +1 -1
- {abstractcore-2.5.3 → abstractcore-2.6.0}/abstractcore.egg-info/PKG-INFO +102 -4
- {abstractcore-2.5.3 → abstractcore-2.6.0}/abstractcore.egg-info/SOURCES.txt +1 -0
- {abstractcore-2.5.3 → abstractcore-2.6.0}/abstractcore.egg-info/requires.txt +9 -0
- {abstractcore-2.5.3 → abstractcore-2.6.0}/pyproject.toml +12 -0
- {abstractcore-2.5.3 → abstractcore-2.6.0}/LICENSE +0 -0
- {abstractcore-2.5.3 → abstractcore-2.6.0}/abstractcore/apps/__init__.py +0 -0
- {abstractcore-2.5.3 → abstractcore-2.6.0}/abstractcore/apps/__main__.py +0 -0
- {abstractcore-2.5.3 → abstractcore-2.6.0}/abstractcore/apps/app_config_utils.py +0 -0
- {abstractcore-2.5.3 → abstractcore-2.6.0}/abstractcore/apps/deepsearch.py +0 -0
- {abstractcore-2.5.3 → abstractcore-2.6.0}/abstractcore/apps/extractor.py +0 -0
- {abstractcore-2.5.3 → abstractcore-2.6.0}/abstractcore/apps/intent.py +0 -0
- {abstractcore-2.5.3 → abstractcore-2.6.0}/abstractcore/apps/judge.py +0 -0
- {abstractcore-2.5.3 → abstractcore-2.6.0}/abstractcore/apps/summarizer.py +0 -0
- {abstractcore-2.5.3 → abstractcore-2.6.0}/abstractcore/architectures/__init__.py +0 -0
- {abstractcore-2.5.3 → abstractcore-2.6.0}/abstractcore/architectures/enums.py +0 -0
- {abstractcore-2.5.3 → abstractcore-2.6.0}/abstractcore/assets/architecture_formats.json +0 -0
- {abstractcore-2.5.3 → abstractcore-2.6.0}/abstractcore/assets/model_capabilities.json +0 -0
- {abstractcore-2.5.3 → abstractcore-2.6.0}/abstractcore/assets/session_schema.json +0 -0
- {abstractcore-2.5.3 → abstractcore-2.6.0}/abstractcore/compression/__init__.py +0 -0
- {abstractcore-2.5.3 → abstractcore-2.6.0}/abstractcore/compression/analytics.py +0 -0
- {abstractcore-2.5.3 → abstractcore-2.6.0}/abstractcore/compression/cache.py +0 -0
- {abstractcore-2.5.3 → abstractcore-2.6.0}/abstractcore/compression/config.py +0 -0
- {abstractcore-2.5.3 → abstractcore-2.6.0}/abstractcore/compression/exceptions.py +0 -0
- {abstractcore-2.5.3 → abstractcore-2.6.0}/abstractcore/compression/glyph_processor.py +0 -0
- {abstractcore-2.5.3 → abstractcore-2.6.0}/abstractcore/compression/optimizer.py +0 -0
- {abstractcore-2.5.3 → abstractcore-2.6.0}/abstractcore/compression/orchestrator.py +0 -0
- {abstractcore-2.5.3 → abstractcore-2.6.0}/abstractcore/compression/pil_text_renderer.py +0 -0
- {abstractcore-2.5.3 → abstractcore-2.6.0}/abstractcore/compression/quality.py +0 -0
- {abstractcore-2.5.3 → abstractcore-2.6.0}/abstractcore/compression/text_formatter.py +0 -0
- {abstractcore-2.5.3 → abstractcore-2.6.0}/abstractcore/compression/vision_compressor.py +0 -0
- {abstractcore-2.5.3 → abstractcore-2.6.0}/abstractcore/config/__init__.py +0 -0
- {abstractcore-2.5.3 → abstractcore-2.6.0}/abstractcore/config/main.py +0 -0
- {abstractcore-2.5.3 → abstractcore-2.6.0}/abstractcore/config/manager.py +0 -0
- {abstractcore-2.5.3 → abstractcore-2.6.0}/abstractcore/config/vision_config.py +0 -0
- {abstractcore-2.5.3 → abstractcore-2.6.0}/abstractcore/core/__init__.py +0 -0
- {abstractcore-2.5.3 → abstractcore-2.6.0}/abstractcore/core/enums.py +0 -0
- {abstractcore-2.5.3 → abstractcore-2.6.0}/abstractcore/core/factory.py +0 -0
- {abstractcore-2.5.3 → abstractcore-2.6.0}/abstractcore/core/interface.py +0 -0
- {abstractcore-2.5.3 → abstractcore-2.6.0}/abstractcore/core/types.py +0 -0
- {abstractcore-2.5.3 → abstractcore-2.6.0}/abstractcore/embeddings/__init__.py +0 -0
- {abstractcore-2.5.3 → abstractcore-2.6.0}/abstractcore/embeddings/models.py +0 -0
- {abstractcore-2.5.3 → abstractcore-2.6.0}/abstractcore/media/__init__.py +0 -0
- {abstractcore-2.5.3 → abstractcore-2.6.0}/abstractcore/media/auto_handler.py +0 -0
- {abstractcore-2.5.3 → abstractcore-2.6.0}/abstractcore/media/base.py +0 -0
- {abstractcore-2.5.3 → abstractcore-2.6.0}/abstractcore/media/capabilities.py +0 -0
- {abstractcore-2.5.3 → abstractcore-2.6.0}/abstractcore/media/handlers/__init__.py +0 -0
- {abstractcore-2.5.3 → abstractcore-2.6.0}/abstractcore/media/handlers/anthropic_handler.py +0 -0
- {abstractcore-2.5.3 → abstractcore-2.6.0}/abstractcore/media/handlers/local_handler.py +0 -0
- {abstractcore-2.5.3 → abstractcore-2.6.0}/abstractcore/media/handlers/openai_handler.py +0 -0
- {abstractcore-2.5.3 → abstractcore-2.6.0}/abstractcore/media/processors/__init__.py +0 -0
- {abstractcore-2.5.3 → abstractcore-2.6.0}/abstractcore/media/processors/direct_pdf_processor.py +0 -0
- {abstractcore-2.5.3 → abstractcore-2.6.0}/abstractcore/media/processors/glyph_pdf_processor.py +0 -0
- {abstractcore-2.5.3 → abstractcore-2.6.0}/abstractcore/media/processors/image_processor.py +0 -0
- {abstractcore-2.5.3 → abstractcore-2.6.0}/abstractcore/media/processors/pdf_processor.py +0 -0
- {abstractcore-2.5.3 → abstractcore-2.6.0}/abstractcore/media/processors/text_processor.py +0 -0
- {abstractcore-2.5.3 → abstractcore-2.6.0}/abstractcore/media/types.py +0 -0
- {abstractcore-2.5.3 → abstractcore-2.6.0}/abstractcore/media/utils/__init__.py +0 -0
- {abstractcore-2.5.3 → abstractcore-2.6.0}/abstractcore/processing/__init__.py +0 -0
- {abstractcore-2.5.3 → abstractcore-2.6.0}/abstractcore/processing/basic_deepsearch.py +0 -0
- {abstractcore-2.5.3 → abstractcore-2.6.0}/abstractcore/processing/basic_extractor.py +0 -0
- {abstractcore-2.5.3 → abstractcore-2.6.0}/abstractcore/processing/basic_intent.py +0 -0
- {abstractcore-2.5.3 → abstractcore-2.6.0}/abstractcore/processing/basic_judge.py +0 -0
- {abstractcore-2.5.3 → abstractcore-2.6.0}/abstractcore/processing/basic_summarizer.py +0 -0
- {abstractcore-2.5.3 → abstractcore-2.6.0}/abstractcore/providers/__init__.py +0 -0
- {abstractcore-2.5.3 → abstractcore-2.6.0}/abstractcore/providers/huggingface_provider.py +0 -0
- {abstractcore-2.5.3 → abstractcore-2.6.0}/abstractcore/providers/mlx_provider.py +0 -0
- {abstractcore-2.5.3 → abstractcore-2.6.0}/abstractcore/providers/model_capabilities.py +0 -0
- {abstractcore-2.5.3 → abstractcore-2.6.0}/abstractcore/providers/registry.py +0 -0
- {abstractcore-2.5.3 → abstractcore-2.6.0}/abstractcore/server/__init__.py +0 -0
- {abstractcore-2.5.3 → abstractcore-2.6.0}/abstractcore/server/app.py +0 -0
- {abstractcore-2.5.3 → abstractcore-2.6.0}/abstractcore/structured/__init__.py +0 -0
- {abstractcore-2.5.3 → abstractcore-2.6.0}/abstractcore/structured/handler.py +0 -0
- {abstractcore-2.5.3 → abstractcore-2.6.0}/abstractcore/structured/retry.py +0 -0
- {abstractcore-2.5.3 → abstractcore-2.6.0}/abstractcore/tools/__init__.py +0 -0
- {abstractcore-2.5.3 → abstractcore-2.6.0}/abstractcore/tools/core.py +0 -0
- {abstractcore-2.5.3 → abstractcore-2.6.0}/abstractcore/utils/__init__.py +0 -0
- {abstractcore-2.5.3 → abstractcore-2.6.0}/abstractcore/utils/cli.py +0 -0
- {abstractcore-2.5.3 → abstractcore-2.6.0}/abstractcore/utils/message_preprocessor.py +0 -0
- {abstractcore-2.5.3 → abstractcore-2.6.0}/abstractcore/utils/structured_logging.py +0 -0
- {abstractcore-2.5.3 → abstractcore-2.6.0}/abstractcore/utils/token_utils.py +0 -0
- {abstractcore-2.5.3 → abstractcore-2.6.0}/abstractcore/utils/trace_export.py +0 -0
- {abstractcore-2.5.3 → abstractcore-2.6.0}/abstractcore/utils/vlm_token_calculator.py +0 -0
- {abstractcore-2.5.3 → abstractcore-2.6.0}/abstractcore.egg-info/dependency_links.txt +0 -0
- {abstractcore-2.5.3 → abstractcore-2.6.0}/abstractcore.egg-info/entry_points.txt +0 -0
- {abstractcore-2.5.3 → abstractcore-2.6.0}/abstractcore.egg-info/top_level.txt +0 -0
- {abstractcore-2.5.3 → abstractcore-2.6.0}/setup.cfg +0 -0
- {abstractcore-2.5.3 → abstractcore-2.6.0}/tests/test_agentic_cli_compatibility.py +0 -0
- {abstractcore-2.5.3 → abstractcore-2.6.0}/tests/test_basic_session.py +0 -0
- {abstractcore-2.5.3 → abstractcore-2.6.0}/tests/test_complete_integration.py +0 -0
- {abstractcore-2.5.3 → abstractcore-2.6.0}/tests/test_comprehensive_events.py +0 -0
- {abstractcore-2.5.3 → abstractcore-2.6.0}/tests/test_core_components.py +0 -0
- {abstractcore-2.5.3 → abstractcore-2.6.0}/tests/test_enhanced_prompt.py +0 -0
- {abstractcore-2.5.3 → abstractcore-2.6.0}/tests/test_environment_variable_tool_call_tags.py +0 -0
- {abstractcore-2.5.3 → abstractcore-2.6.0}/tests/test_factory.py +0 -0
- {abstractcore-2.5.3 → abstractcore-2.6.0}/tests/test_final_accuracy.py +0 -0
- {abstractcore-2.5.3 → abstractcore-2.6.0}/tests/test_final_comprehensive.py +0 -0
- {abstractcore-2.5.3 → abstractcore-2.6.0}/tests/test_final_graceful_errors.py +0 -0
- {abstractcore-2.5.3 → abstractcore-2.6.0}/tests/test_graceful_fallback.py +0 -0
- {abstractcore-2.5.3 → abstractcore-2.6.0}/tests/test_import_debug.py +0 -0
- {abstractcore-2.5.3 → abstractcore-2.6.0}/tests/test_integrated_functionality.py +0 -0
- {abstractcore-2.5.3 → abstractcore-2.6.0}/tests/test_retry_observability.py +0 -0
- {abstractcore-2.5.3 → abstractcore-2.6.0}/tests/test_retry_strategy.py +0 -0
- {abstractcore-2.5.3 → abstractcore-2.6.0}/tests/test_seed_determinism.py +0 -0
- {abstractcore-2.5.3 → abstractcore-2.6.0}/tests/test_seed_temperature_basic.py +0 -0
- {abstractcore-2.5.3 → abstractcore-2.6.0}/tests/test_sensory_prompting.py +0 -0
- {abstractcore-2.5.3 → abstractcore-2.6.0}/tests/test_text_only_model_experience.py +0 -0
- {abstractcore-2.5.3 → abstractcore-2.6.0}/tests/test_unload_memory.py +0 -0
- {abstractcore-2.5.3 → abstractcore-2.6.0}/tests/test_user_scenario_validation.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: abstractcore
|
|
3
|
-
Version: 2.
|
|
3
|
+
Version: 2.6.0
|
|
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>
|
|
@@ -67,12 +67,18 @@ Provides-Extra: api-providers
|
|
|
67
67
|
Requires-Dist: abstractcore[anthropic,openai]; extra == "api-providers"
|
|
68
68
|
Provides-Extra: local-providers
|
|
69
69
|
Requires-Dist: abstractcore[lmstudio,mlx,ollama]; extra == "local-providers"
|
|
70
|
+
Provides-Extra: local-providers-non-mlx
|
|
71
|
+
Requires-Dist: abstractcore[lmstudio,ollama]; extra == "local-providers-non-mlx"
|
|
70
72
|
Provides-Extra: heavy-providers
|
|
71
73
|
Requires-Dist: abstractcore[huggingface]; extra == "heavy-providers"
|
|
72
74
|
Provides-Extra: all-providers
|
|
73
75
|
Requires-Dist: abstractcore[anthropic,embeddings,huggingface,lmstudio,mlx,ollama,openai]; extra == "all-providers"
|
|
76
|
+
Provides-Extra: all-providers-non-mlx
|
|
77
|
+
Requires-Dist: abstractcore[anthropic,embeddings,huggingface,lmstudio,ollama,openai]; extra == "all-providers-non-mlx"
|
|
74
78
|
Provides-Extra: all
|
|
75
79
|
Requires-Dist: abstractcore[anthropic,compression,dev,docs,embeddings,huggingface,lmstudio,media,mlx,ollama,openai,processing,server,test,tools]; extra == "all"
|
|
80
|
+
Provides-Extra: all-non-mlx
|
|
81
|
+
Requires-Dist: abstractcore[anthropic,compression,dev,docs,embeddings,huggingface,lmstudio,media,ollama,openai,processing,server,test,tools]; extra == "all-non-mlx"
|
|
76
82
|
Provides-Extra: lightweight
|
|
77
83
|
Requires-Dist: abstractcore[anthropic,compression,embeddings,lmstudio,media,ollama,openai,processing,server,tools]; extra == "lightweight"
|
|
78
84
|
Provides-Extra: dev
|
|
@@ -120,7 +126,11 @@ A unified Python library for interaction with multiple Large Language Model (LLM
|
|
|
120
126
|
### Installation
|
|
121
127
|
|
|
122
128
|
```bash
|
|
129
|
+
# macOS/Apple Silicon (includes MLX)
|
|
123
130
|
pip install abstractcore[all]
|
|
131
|
+
|
|
132
|
+
# Linux/Windows (excludes MLX)
|
|
133
|
+
pip install abstractcore[all-non-mlx]
|
|
124
134
|
```
|
|
125
135
|
|
|
126
136
|
### Basic Usage
|
|
@@ -311,6 +321,69 @@ export_traces(traces, format='markdown', file_path='workflow_trace.md')
|
|
|
311
321
|
|
|
312
322
|
[Learn more about Interaction Tracing](docs/interaction-tracing.md)
|
|
313
323
|
|
|
324
|
+
### Async/Await Support
|
|
325
|
+
|
|
326
|
+
Execute concurrent LLM requests for batch operations, multi-provider comparisons, or non-blocking web applications. **Production-ready with validated 6-7.5x performance improvement** for concurrent requests.
|
|
327
|
+
|
|
328
|
+
```python
|
|
329
|
+
import asyncio
|
|
330
|
+
from abstractcore import create_llm
|
|
331
|
+
|
|
332
|
+
async def main():
|
|
333
|
+
llm = create_llm("openai", model="gpt-4o-mini")
|
|
334
|
+
|
|
335
|
+
# Execute 3 requests concurrently (6-7x faster!)
|
|
336
|
+
tasks = [
|
|
337
|
+
llm.agenerate(f"Summarize {topic}")
|
|
338
|
+
for topic in ["Python", "JavaScript", "Rust"]
|
|
339
|
+
]
|
|
340
|
+
responses = await asyncio.gather(*tasks)
|
|
341
|
+
|
|
342
|
+
for response in responses:
|
|
343
|
+
print(response.content)
|
|
344
|
+
|
|
345
|
+
asyncio.run(main())
|
|
346
|
+
```
|
|
347
|
+
|
|
348
|
+
**Performance (Validated with Real Testing):**
|
|
349
|
+
- **Ollama**: 7.5x faster for concurrent requests
|
|
350
|
+
- **LMStudio**: 6.5x faster for concurrent requests
|
|
351
|
+
- **OpenAI**: 6.0x faster for concurrent requests
|
|
352
|
+
- **Anthropic**: 7.4x faster for concurrent requests
|
|
353
|
+
- **Average**: ~7x speedup across all providers
|
|
354
|
+
|
|
355
|
+
**Native Async vs Fallback:**
|
|
356
|
+
- **Native async** (httpx.AsyncClient): Ollama, LMStudio, OpenAI, Anthropic
|
|
357
|
+
- **Fallback** (asyncio.to_thread): MLX, HuggingFace
|
|
358
|
+
- All providers work seamlessly - fallback keeps event loop responsive
|
|
359
|
+
|
|
360
|
+
**Use Cases:**
|
|
361
|
+
- Batch operations with 6-7x speedup via parallel execution
|
|
362
|
+
- Multi-provider comparisons (query OpenAI and Anthropic simultaneously)
|
|
363
|
+
- FastAPI/async web frameworks integration
|
|
364
|
+
- Session async for conversation management
|
|
365
|
+
|
|
366
|
+
**Works with:**
|
|
367
|
+
- All 6 providers (OpenAI, Anthropic, Ollama, LMStudio, MLX, HuggingFace)
|
|
368
|
+
- Streaming via `async for chunk in llm.agenerate(..., stream=True)`
|
|
369
|
+
- Sessions via `await session.agenerate(...)`
|
|
370
|
+
- Zero breaking changes to sync API
|
|
371
|
+
|
|
372
|
+
**Learn async patterns:**
|
|
373
|
+
|
|
374
|
+
AbstractCore includes an educational [async CLI demo](examples/async_cli_demo.py) that demonstrates 8 core async/await patterns:
|
|
375
|
+
- Event-driven progress with GlobalEventBus
|
|
376
|
+
- Parallel tool execution with asyncio.gather()
|
|
377
|
+
- Proper async streaming pattern (await first, then async for)
|
|
378
|
+
- Non-blocking animations and user input
|
|
379
|
+
|
|
380
|
+
```bash
|
|
381
|
+
# Try the educational async demo
|
|
382
|
+
python examples/async_cli_demo.py --provider ollama --model qwen3:4b --stream
|
|
383
|
+
```
|
|
384
|
+
|
|
385
|
+
[Learn more in CLI docs](docs/acore-cli.md#async-cli-demo-educational-reference)
|
|
386
|
+
|
|
314
387
|
### Media Handling
|
|
315
388
|
|
|
316
389
|
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.
|
|
@@ -408,7 +481,8 @@ if response.metadata and response.metadata.get('compression_used'):
|
|
|
408
481
|
|
|
409
482
|
- **Offline-First Design**: Built primarily for open source LLMs with full offline capability. Download once, run forever without internet access
|
|
410
483
|
- **Provider Agnostic**: Seamlessly switch between OpenAI, Anthropic, Ollama, LMStudio, MLX, HuggingFace
|
|
411
|
-
- **
|
|
484
|
+
- **Async/Await Support** ⭐ NEW in v2.6.0: Native async support for concurrent requests with `asyncio.gather()` - works with all 6 providers
|
|
485
|
+
- **Interaction Tracing**: Complete LLM observability with programmatic access to prompts, responses, tokens, timing, and trace correlation for debugging, trust, and compliance
|
|
412
486
|
- **Glyph Visual-Text Compression**: Revolutionary compression system that renders text as optimized images for 3-4x token compression and faster inference
|
|
413
487
|
- **Centralized Configuration**: Global defaults and app-specific preferences at `~/.abstractcore/config/abstractcore.json`
|
|
414
488
|
- **Intelligent Media Handling**: Upload images, PDFs, and documents with automatic maximum resolution optimization
|
|
@@ -522,7 +596,7 @@ python -m abstractcore.utils.cli --provider anthropic --model claude-3-5-haiku-l
|
|
|
522
596
|
|
|
523
597
|
## Built-in Applications (Ready-to-Use CLI Tools)
|
|
524
598
|
|
|
525
|
-
AbstractCore includes **
|
|
599
|
+
AbstractCore includes **five 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.
|
|
526
600
|
|
|
527
601
|
### Available Applications
|
|
528
602
|
|
|
@@ -532,6 +606,7 @@ AbstractCore includes **four specialized command-line applications** for common
|
|
|
532
606
|
| **Extractor** | Entity and relationship extraction | `extractor` |
|
|
533
607
|
| **Judge** | Text evaluation and scoring | `judge` |
|
|
534
608
|
| **Intent Analyzer** | Psychological intent analysis & deception detection | `intent` |
|
|
609
|
+
| **DeepSearch** | Autonomous multi-stage research with web search | `deepsearch` |
|
|
535
610
|
|
|
536
611
|
### Quick Usage Examples
|
|
537
612
|
|
|
@@ -555,6 +630,11 @@ judge proposal.md --custom-criteria has_examples,covers_risks --output assessmen
|
|
|
555
630
|
intent conversation.txt --focus-participant user --depth comprehensive
|
|
556
631
|
intent email.txt --format plain --context document --verbose
|
|
557
632
|
intent chat_log.json --conversation-mode --provider lmstudio --model qwen/qwen3-30b-a3b-2507
|
|
633
|
+
|
|
634
|
+
# Autonomous research with web search and reflexive refinement
|
|
635
|
+
deepsearch "What are the latest advances in quantum computing?" --depth comprehensive
|
|
636
|
+
deepsearch "AI impact on healthcare" --focus "diagnosis,treatment,ethics" --reflexive
|
|
637
|
+
deepsearch "sustainable energy 2025" --max-sources 25 --provider openai --model gpt-4o-mini
|
|
558
638
|
```
|
|
559
639
|
|
|
560
640
|
### Installation & Setup
|
|
@@ -567,9 +647,10 @@ pip install abstractcore[all]
|
|
|
567
647
|
|
|
568
648
|
# Apps are immediately available
|
|
569
649
|
summarizer --help
|
|
570
|
-
extractor --help
|
|
650
|
+
extractor --help
|
|
571
651
|
judge --help
|
|
572
652
|
intent --help
|
|
653
|
+
deepsearch --help
|
|
573
654
|
```
|
|
574
655
|
|
|
575
656
|
### Alternative Usage Methods
|
|
@@ -580,12 +661,14 @@ summarizer document.txt
|
|
|
580
661
|
extractor report.pdf
|
|
581
662
|
judge essay.md
|
|
582
663
|
intent conversation.txt
|
|
664
|
+
deepsearch "your research query"
|
|
583
665
|
|
|
584
666
|
# Method 2: Via Python module
|
|
585
667
|
python -m abstractcore.apps summarizer document.txt
|
|
586
668
|
python -m abstractcore.apps extractor report.pdf
|
|
587
669
|
python -m abstractcore.apps judge essay.md
|
|
588
670
|
python -m abstractcore.apps intent conversation.txt
|
|
671
|
+
python -m abstractcore.apps deepsearch "your research query"
|
|
589
672
|
```
|
|
590
673
|
|
|
591
674
|
### Key Parameters
|
|
@@ -633,6 +716,7 @@ Each application has documentation with examples and usage information:
|
|
|
633
716
|
- **[Extractor Guide](docs/apps/basic-extractor.md)** - Entity and relationship extraction
|
|
634
717
|
- **[Intent Analyzer Guide](docs/apps/basic-intent.md)** - Psychological intent analysis and deception detection
|
|
635
718
|
- **[Judge Guide](docs/apps/basic-judge.md)** - Text evaluation and scoring systems
|
|
719
|
+
- **[DeepSearch Guide](docs/apps/basic-deepsearch.md)** - Autonomous multi-stage research with web search
|
|
636
720
|
|
|
637
721
|
**When to use the apps:**
|
|
638
722
|
- Processing documents without writing code
|
|
@@ -878,6 +962,9 @@ pip install abstractcore[media]
|
|
|
878
962
|
pip install abstractcore[openai]
|
|
879
963
|
pip install abstractcore[anthropic]
|
|
880
964
|
pip install abstractcore[ollama]
|
|
965
|
+
pip install abstractcore[lmstudio]
|
|
966
|
+
pip install abstractcore[huggingface]
|
|
967
|
+
pip install abstractcore[mlx] # macOS/Apple Silicon only
|
|
881
968
|
|
|
882
969
|
# With server support
|
|
883
970
|
pip install abstractcore[server]
|
|
@@ -887,6 +974,16 @@ pip install abstractcore[embeddings]
|
|
|
887
974
|
|
|
888
975
|
# Everything (recommended)
|
|
889
976
|
pip install abstractcore[all]
|
|
977
|
+
|
|
978
|
+
# Cross-platform (all except MLX - for Linux/Windows)
|
|
979
|
+
pip install abstractcore[all-non-mlx]
|
|
980
|
+
|
|
981
|
+
# Provider groups
|
|
982
|
+
pip install abstractcore[all-providers] # All providers (includes MLX)
|
|
983
|
+
pip install abstractcore[all-providers-non-mlx] # All providers except MLX
|
|
984
|
+
pip install abstractcore[local-providers] # Ollama, LMStudio, MLX
|
|
985
|
+
pip install abstractcore[local-providers-non-mlx] # Ollama, LMStudio only
|
|
986
|
+
pip install abstractcore[api-providers] # OpenAI, Anthropic
|
|
890
987
|
```
|
|
891
988
|
|
|
892
989
|
**Media processing extras:**
|
|
@@ -917,6 +1014,7 @@ All tests passing as of October 12th, 2025.
|
|
|
917
1014
|
## Quick Links
|
|
918
1015
|
|
|
919
1016
|
- **[📚 Documentation Index](docs/)** - Complete documentation navigation guide
|
|
1017
|
+
- **[🔍 Interaction Tracing](docs/interaction-tracing.md)** - LLM observability and debugging ⭐ NEW
|
|
920
1018
|
- **[Getting Started](docs/getting-started.md)** - 5-minute quick start
|
|
921
1019
|
- **[⚙️ Prerequisites](docs/prerequisites.md)** - Provider setup (OpenAI, Anthropic, Ollama, etc.)
|
|
922
1020
|
- **[📖 Python API](docs/api-reference.md)** - Complete Python API reference
|
|
@@ -14,7 +14,11 @@ A unified Python library for interaction with multiple Large Language Model (LLM
|
|
|
14
14
|
### Installation
|
|
15
15
|
|
|
16
16
|
```bash
|
|
17
|
+
# macOS/Apple Silicon (includes MLX)
|
|
17
18
|
pip install abstractcore[all]
|
|
19
|
+
|
|
20
|
+
# Linux/Windows (excludes MLX)
|
|
21
|
+
pip install abstractcore[all-non-mlx]
|
|
18
22
|
```
|
|
19
23
|
|
|
20
24
|
### Basic Usage
|
|
@@ -205,6 +209,69 @@ export_traces(traces, format='markdown', file_path='workflow_trace.md')
|
|
|
205
209
|
|
|
206
210
|
[Learn more about Interaction Tracing](docs/interaction-tracing.md)
|
|
207
211
|
|
|
212
|
+
### Async/Await Support
|
|
213
|
+
|
|
214
|
+
Execute concurrent LLM requests for batch operations, multi-provider comparisons, or non-blocking web applications. **Production-ready with validated 6-7.5x performance improvement** for concurrent requests.
|
|
215
|
+
|
|
216
|
+
```python
|
|
217
|
+
import asyncio
|
|
218
|
+
from abstractcore import create_llm
|
|
219
|
+
|
|
220
|
+
async def main():
|
|
221
|
+
llm = create_llm("openai", model="gpt-4o-mini")
|
|
222
|
+
|
|
223
|
+
# Execute 3 requests concurrently (6-7x faster!)
|
|
224
|
+
tasks = [
|
|
225
|
+
llm.agenerate(f"Summarize {topic}")
|
|
226
|
+
for topic in ["Python", "JavaScript", "Rust"]
|
|
227
|
+
]
|
|
228
|
+
responses = await asyncio.gather(*tasks)
|
|
229
|
+
|
|
230
|
+
for response in responses:
|
|
231
|
+
print(response.content)
|
|
232
|
+
|
|
233
|
+
asyncio.run(main())
|
|
234
|
+
```
|
|
235
|
+
|
|
236
|
+
**Performance (Validated with Real Testing):**
|
|
237
|
+
- **Ollama**: 7.5x faster for concurrent requests
|
|
238
|
+
- **LMStudio**: 6.5x faster for concurrent requests
|
|
239
|
+
- **OpenAI**: 6.0x faster for concurrent requests
|
|
240
|
+
- **Anthropic**: 7.4x faster for concurrent requests
|
|
241
|
+
- **Average**: ~7x speedup across all providers
|
|
242
|
+
|
|
243
|
+
**Native Async vs Fallback:**
|
|
244
|
+
- **Native async** (httpx.AsyncClient): Ollama, LMStudio, OpenAI, Anthropic
|
|
245
|
+
- **Fallback** (asyncio.to_thread): MLX, HuggingFace
|
|
246
|
+
- All providers work seamlessly - fallback keeps event loop responsive
|
|
247
|
+
|
|
248
|
+
**Use Cases:**
|
|
249
|
+
- Batch operations with 6-7x speedup via parallel execution
|
|
250
|
+
- Multi-provider comparisons (query OpenAI and Anthropic simultaneously)
|
|
251
|
+
- FastAPI/async web frameworks integration
|
|
252
|
+
- Session async for conversation management
|
|
253
|
+
|
|
254
|
+
**Works with:**
|
|
255
|
+
- All 6 providers (OpenAI, Anthropic, Ollama, LMStudio, MLX, HuggingFace)
|
|
256
|
+
- Streaming via `async for chunk in llm.agenerate(..., stream=True)`
|
|
257
|
+
- Sessions via `await session.agenerate(...)`
|
|
258
|
+
- Zero breaking changes to sync API
|
|
259
|
+
|
|
260
|
+
**Learn async patterns:**
|
|
261
|
+
|
|
262
|
+
AbstractCore includes an educational [async CLI demo](examples/async_cli_demo.py) that demonstrates 8 core async/await patterns:
|
|
263
|
+
- Event-driven progress with GlobalEventBus
|
|
264
|
+
- Parallel tool execution with asyncio.gather()
|
|
265
|
+
- Proper async streaming pattern (await first, then async for)
|
|
266
|
+
- Non-blocking animations and user input
|
|
267
|
+
|
|
268
|
+
```bash
|
|
269
|
+
# Try the educational async demo
|
|
270
|
+
python examples/async_cli_demo.py --provider ollama --model qwen3:4b --stream
|
|
271
|
+
```
|
|
272
|
+
|
|
273
|
+
[Learn more in CLI docs](docs/acore-cli.md#async-cli-demo-educational-reference)
|
|
274
|
+
|
|
208
275
|
### Media Handling
|
|
209
276
|
|
|
210
277
|
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.
|
|
@@ -302,7 +369,8 @@ if response.metadata and response.metadata.get('compression_used'):
|
|
|
302
369
|
|
|
303
370
|
- **Offline-First Design**: Built primarily for open source LLMs with full offline capability. Download once, run forever without internet access
|
|
304
371
|
- **Provider Agnostic**: Seamlessly switch between OpenAI, Anthropic, Ollama, LMStudio, MLX, HuggingFace
|
|
305
|
-
- **
|
|
372
|
+
- **Async/Await Support** ⭐ NEW in v2.6.0: Native async support for concurrent requests with `asyncio.gather()` - works with all 6 providers
|
|
373
|
+
- **Interaction Tracing**: Complete LLM observability with programmatic access to prompts, responses, tokens, timing, and trace correlation for debugging, trust, and compliance
|
|
306
374
|
- **Glyph Visual-Text Compression**: Revolutionary compression system that renders text as optimized images for 3-4x token compression and faster inference
|
|
307
375
|
- **Centralized Configuration**: Global defaults and app-specific preferences at `~/.abstractcore/config/abstractcore.json`
|
|
308
376
|
- **Intelligent Media Handling**: Upload images, PDFs, and documents with automatic maximum resolution optimization
|
|
@@ -416,7 +484,7 @@ python -m abstractcore.utils.cli --provider anthropic --model claude-3-5-haiku-l
|
|
|
416
484
|
|
|
417
485
|
## Built-in Applications (Ready-to-Use CLI Tools)
|
|
418
486
|
|
|
419
|
-
AbstractCore includes **
|
|
487
|
+
AbstractCore includes **five 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.
|
|
420
488
|
|
|
421
489
|
### Available Applications
|
|
422
490
|
|
|
@@ -426,6 +494,7 @@ AbstractCore includes **four specialized command-line applications** for common
|
|
|
426
494
|
| **Extractor** | Entity and relationship extraction | `extractor` |
|
|
427
495
|
| **Judge** | Text evaluation and scoring | `judge` |
|
|
428
496
|
| **Intent Analyzer** | Psychological intent analysis & deception detection | `intent` |
|
|
497
|
+
| **DeepSearch** | Autonomous multi-stage research with web search | `deepsearch` |
|
|
429
498
|
|
|
430
499
|
### Quick Usage Examples
|
|
431
500
|
|
|
@@ -449,6 +518,11 @@ judge proposal.md --custom-criteria has_examples,covers_risks --output assessmen
|
|
|
449
518
|
intent conversation.txt --focus-participant user --depth comprehensive
|
|
450
519
|
intent email.txt --format plain --context document --verbose
|
|
451
520
|
intent chat_log.json --conversation-mode --provider lmstudio --model qwen/qwen3-30b-a3b-2507
|
|
521
|
+
|
|
522
|
+
# Autonomous research with web search and reflexive refinement
|
|
523
|
+
deepsearch "What are the latest advances in quantum computing?" --depth comprehensive
|
|
524
|
+
deepsearch "AI impact on healthcare" --focus "diagnosis,treatment,ethics" --reflexive
|
|
525
|
+
deepsearch "sustainable energy 2025" --max-sources 25 --provider openai --model gpt-4o-mini
|
|
452
526
|
```
|
|
453
527
|
|
|
454
528
|
### Installation & Setup
|
|
@@ -461,9 +535,10 @@ pip install abstractcore[all]
|
|
|
461
535
|
|
|
462
536
|
# Apps are immediately available
|
|
463
537
|
summarizer --help
|
|
464
|
-
extractor --help
|
|
538
|
+
extractor --help
|
|
465
539
|
judge --help
|
|
466
540
|
intent --help
|
|
541
|
+
deepsearch --help
|
|
467
542
|
```
|
|
468
543
|
|
|
469
544
|
### Alternative Usage Methods
|
|
@@ -474,12 +549,14 @@ summarizer document.txt
|
|
|
474
549
|
extractor report.pdf
|
|
475
550
|
judge essay.md
|
|
476
551
|
intent conversation.txt
|
|
552
|
+
deepsearch "your research query"
|
|
477
553
|
|
|
478
554
|
# Method 2: Via Python module
|
|
479
555
|
python -m abstractcore.apps summarizer document.txt
|
|
480
556
|
python -m abstractcore.apps extractor report.pdf
|
|
481
557
|
python -m abstractcore.apps judge essay.md
|
|
482
558
|
python -m abstractcore.apps intent conversation.txt
|
|
559
|
+
python -m abstractcore.apps deepsearch "your research query"
|
|
483
560
|
```
|
|
484
561
|
|
|
485
562
|
### Key Parameters
|
|
@@ -527,6 +604,7 @@ Each application has documentation with examples and usage information:
|
|
|
527
604
|
- **[Extractor Guide](docs/apps/basic-extractor.md)** - Entity and relationship extraction
|
|
528
605
|
- **[Intent Analyzer Guide](docs/apps/basic-intent.md)** - Psychological intent analysis and deception detection
|
|
529
606
|
- **[Judge Guide](docs/apps/basic-judge.md)** - Text evaluation and scoring systems
|
|
607
|
+
- **[DeepSearch Guide](docs/apps/basic-deepsearch.md)** - Autonomous multi-stage research with web search
|
|
530
608
|
|
|
531
609
|
**When to use the apps:**
|
|
532
610
|
- Processing documents without writing code
|
|
@@ -772,6 +850,9 @@ pip install abstractcore[media]
|
|
|
772
850
|
pip install abstractcore[openai]
|
|
773
851
|
pip install abstractcore[anthropic]
|
|
774
852
|
pip install abstractcore[ollama]
|
|
853
|
+
pip install abstractcore[lmstudio]
|
|
854
|
+
pip install abstractcore[huggingface]
|
|
855
|
+
pip install abstractcore[mlx] # macOS/Apple Silicon only
|
|
775
856
|
|
|
776
857
|
# With server support
|
|
777
858
|
pip install abstractcore[server]
|
|
@@ -781,6 +862,16 @@ pip install abstractcore[embeddings]
|
|
|
781
862
|
|
|
782
863
|
# Everything (recommended)
|
|
783
864
|
pip install abstractcore[all]
|
|
865
|
+
|
|
866
|
+
# Cross-platform (all except MLX - for Linux/Windows)
|
|
867
|
+
pip install abstractcore[all-non-mlx]
|
|
868
|
+
|
|
869
|
+
# Provider groups
|
|
870
|
+
pip install abstractcore[all-providers] # All providers (includes MLX)
|
|
871
|
+
pip install abstractcore[all-providers-non-mlx] # All providers except MLX
|
|
872
|
+
pip install abstractcore[local-providers] # Ollama, LMStudio, MLX
|
|
873
|
+
pip install abstractcore[local-providers-non-mlx] # Ollama, LMStudio only
|
|
874
|
+
pip install abstractcore[api-providers] # OpenAI, Anthropic
|
|
784
875
|
```
|
|
785
876
|
|
|
786
877
|
**Media processing extras:**
|
|
@@ -811,6 +902,7 @@ All tests passing as of October 12th, 2025.
|
|
|
811
902
|
## Quick Links
|
|
812
903
|
|
|
813
904
|
- **[📚 Documentation Index](docs/)** - Complete documentation navigation guide
|
|
905
|
+
- **[🔍 Interaction Tracing](docs/interaction-tracing.md)** - LLM observability and debugging ⭐ NEW
|
|
814
906
|
- **[Getting Started](docs/getting-started.md)** - 5-minute quick start
|
|
815
907
|
- **[⚙️ Prerequisites](docs/prerequisites.md)** - Provider setup (OpenAI, Anthropic, Ollama, etc.)
|
|
816
908
|
- **[📖 Python API](docs/api-reference.md)** - Complete Python API reference
|
|
@@ -49,6 +49,9 @@ _has_processing = True
|
|
|
49
49
|
# Tools module (core functionality)
|
|
50
50
|
from .tools import tool
|
|
51
51
|
|
|
52
|
+
# Download module (core functionality)
|
|
53
|
+
from .download import download_model, DownloadProgress, DownloadStatus
|
|
54
|
+
|
|
52
55
|
# Compression module (optional import)
|
|
53
56
|
try:
|
|
54
57
|
from .compression import GlyphConfig, CompressionOrchestrator
|
|
@@ -67,7 +70,10 @@ __all__ = [
|
|
|
67
70
|
'ModelNotFoundError',
|
|
68
71
|
'ProviderAPIError',
|
|
69
72
|
'AuthenticationError',
|
|
70
|
-
'tool'
|
|
73
|
+
'tool',
|
|
74
|
+
'download_model',
|
|
75
|
+
'DownloadProgress',
|
|
76
|
+
'DownloadStatus',
|
|
71
77
|
]
|
|
72
78
|
|
|
73
79
|
if _has_embeddings:
|
|
@@ -9,9 +9,9 @@ import json
|
|
|
9
9
|
import os
|
|
10
10
|
from typing import Dict, Any, Optional, List
|
|
11
11
|
from pathlib import Path
|
|
12
|
-
import
|
|
12
|
+
from ..utils.structured_logging import get_logger
|
|
13
13
|
|
|
14
|
-
logger =
|
|
14
|
+
logger = get_logger(__name__)
|
|
15
15
|
|
|
16
16
|
# Cache for loaded JSON data
|
|
17
17
|
_architecture_formats: Optional[Dict[str, Any]] = None
|
|
@@ -8,13 +8,13 @@ and production LLM system requirements.
|
|
|
8
8
|
|
|
9
9
|
import time
|
|
10
10
|
import random
|
|
11
|
-
import logging
|
|
12
11
|
from typing import Type, Optional, Set, Dict, Any
|
|
13
12
|
from dataclasses import dataclass
|
|
14
13
|
from datetime import datetime, timedelta
|
|
15
14
|
from enum import Enum
|
|
15
|
+
from ..utils.structured_logging import get_logger
|
|
16
16
|
|
|
17
|
-
logger =
|
|
17
|
+
logger = get_logger(__name__)
|
|
18
18
|
|
|
19
19
|
|
|
20
20
|
class RetryableErrorType(Enum):
|
|
@@ -3,11 +3,12 @@ BasicSession for conversation tracking.
|
|
|
3
3
|
Target: <500 lines maximum.
|
|
4
4
|
"""
|
|
5
5
|
|
|
6
|
-
from typing import List, Optional, Dict, Any, Union, Iterator, Callable
|
|
6
|
+
from typing import List, Optional, Dict, Any, Union, Iterator, AsyncIterator, Callable
|
|
7
7
|
from datetime import datetime
|
|
8
8
|
from pathlib import Path
|
|
9
9
|
import json
|
|
10
10
|
import uuid
|
|
11
|
+
import asyncio
|
|
11
12
|
from collections.abc import Generator
|
|
12
13
|
|
|
13
14
|
from .interface import AbstractCoreInterface
|
|
@@ -273,6 +274,136 @@ class BasicSession:
|
|
|
273
274
|
if collected_content:
|
|
274
275
|
self.add_message('assistant', collected_content)
|
|
275
276
|
|
|
277
|
+
async def agenerate(self,
|
|
278
|
+
prompt: str,
|
|
279
|
+
name: Optional[str] = None,
|
|
280
|
+
location: Optional[str] = None,
|
|
281
|
+
**kwargs) -> Union[GenerateResponse, AsyncIterator[GenerateResponse]]:
|
|
282
|
+
"""
|
|
283
|
+
Async generation with conversation history.
|
|
284
|
+
|
|
285
|
+
Args:
|
|
286
|
+
prompt: User message
|
|
287
|
+
name: Optional speaker name
|
|
288
|
+
location: Optional location context
|
|
289
|
+
**kwargs: Generation parameters (stream, temperature, etc.)
|
|
290
|
+
|
|
291
|
+
Returns:
|
|
292
|
+
GenerateResponse or AsyncIterator for streaming
|
|
293
|
+
|
|
294
|
+
Example:
|
|
295
|
+
# Async chat interaction
|
|
296
|
+
response = await session.agenerate('What is Python?')
|
|
297
|
+
|
|
298
|
+
# Async streaming
|
|
299
|
+
async for chunk in await session.agenerate('Tell me a story', stream=True):
|
|
300
|
+
print(chunk.content, end='')
|
|
301
|
+
"""
|
|
302
|
+
if not self.provider:
|
|
303
|
+
raise ValueError("No provider configured")
|
|
304
|
+
|
|
305
|
+
# Check for auto-compaction before generating
|
|
306
|
+
if self.auto_compact and self.should_compact(self.auto_compact_threshold):
|
|
307
|
+
print(f"🗜️ Auto-compacting session (tokens: {self.get_token_estimate()} > {self.auto_compact_threshold})")
|
|
308
|
+
compacted = self.compact(reason="auto_threshold")
|
|
309
|
+
# Replace current session with compacted version
|
|
310
|
+
self._replace_with_compacted(compacted)
|
|
311
|
+
|
|
312
|
+
# Pre-processing (fast, sync is fine)
|
|
313
|
+
self.add_message('user', prompt, name=name, location=location)
|
|
314
|
+
|
|
315
|
+
# Format messages for provider (exclude the current user message since provider will add it)
|
|
316
|
+
messages = self._format_messages_for_provider_excluding_current()
|
|
317
|
+
|
|
318
|
+
# Use session tools if not provided in kwargs
|
|
319
|
+
if 'tools' not in kwargs and self.tools:
|
|
320
|
+
kwargs['tools'] = self.tools
|
|
321
|
+
|
|
322
|
+
# Pass session tool_call_tags if available and not overridden in kwargs
|
|
323
|
+
if hasattr(self, 'tool_call_tags') and self.tool_call_tags is not None and 'tool_call_tags' not in kwargs:
|
|
324
|
+
kwargs['tool_call_tags'] = self.tool_call_tags
|
|
325
|
+
|
|
326
|
+
# Extract media parameter explicitly
|
|
327
|
+
media = kwargs.pop('media', None)
|
|
328
|
+
|
|
329
|
+
# Add session-level parameters if not overridden in kwargs
|
|
330
|
+
if 'temperature' not in kwargs and self.temperature is not None:
|
|
331
|
+
kwargs['temperature'] = self.temperature
|
|
332
|
+
if 'seed' not in kwargs and self.seed is not None:
|
|
333
|
+
kwargs['seed'] = self.seed
|
|
334
|
+
|
|
335
|
+
# Add trace metadata if tracing is enabled
|
|
336
|
+
if self.enable_tracing:
|
|
337
|
+
if 'trace_metadata' not in kwargs:
|
|
338
|
+
kwargs['trace_metadata'] = {}
|
|
339
|
+
kwargs['trace_metadata'].update({
|
|
340
|
+
'session_id': self.id,
|
|
341
|
+
'step_type': kwargs.get('step_type', 'chat'),
|
|
342
|
+
'attempt_number': kwargs.get('attempt_number', 1)
|
|
343
|
+
})
|
|
344
|
+
|
|
345
|
+
# Check if streaming
|
|
346
|
+
stream = kwargs.get('stream', False)
|
|
347
|
+
|
|
348
|
+
if stream:
|
|
349
|
+
# Return async streaming wrapper that adds assistant message after
|
|
350
|
+
return self._async_session_stream(prompt, messages, media, **kwargs)
|
|
351
|
+
else:
|
|
352
|
+
# Async generation
|
|
353
|
+
response = await self.provider.agenerate(
|
|
354
|
+
prompt=prompt,
|
|
355
|
+
messages=messages,
|
|
356
|
+
system_prompt=self.system_prompt,
|
|
357
|
+
media=media,
|
|
358
|
+
**kwargs
|
|
359
|
+
)
|
|
360
|
+
|
|
361
|
+
# Post-processing (fast, sync is fine)
|
|
362
|
+
if hasattr(response, 'content') and response.content:
|
|
363
|
+
self.add_message('assistant', response.content)
|
|
364
|
+
|
|
365
|
+
# Capture trace if enabled and available
|
|
366
|
+
if self.enable_tracing and hasattr(self.provider, 'get_traces'):
|
|
367
|
+
if hasattr(response, 'metadata') and response.metadata and 'trace_id' in response.metadata:
|
|
368
|
+
trace = self.provider.get_traces(response.metadata['trace_id'])
|
|
369
|
+
if trace:
|
|
370
|
+
self.interaction_traces.append(trace)
|
|
371
|
+
|
|
372
|
+
return response
|
|
373
|
+
|
|
374
|
+
async def _async_session_stream(self,
|
|
375
|
+
prompt: str,
|
|
376
|
+
messages: List[Dict[str, str]],
|
|
377
|
+
media: Optional[List],
|
|
378
|
+
**kwargs) -> AsyncIterator[GenerateResponse]:
|
|
379
|
+
"""Async streaming with session history management."""
|
|
380
|
+
collected_content = ""
|
|
381
|
+
|
|
382
|
+
# Remove 'stream' from kwargs since we're explicitly setting it
|
|
383
|
+
kwargs_copy = {k: v for k, v in kwargs.items() if k != 'stream'}
|
|
384
|
+
|
|
385
|
+
# CRITICAL: Await first to get async generator, then iterate
|
|
386
|
+
stream_gen = await self.provider.agenerate(
|
|
387
|
+
prompt=prompt,
|
|
388
|
+
messages=messages,
|
|
389
|
+
system_prompt=self.system_prompt,
|
|
390
|
+
media=media,
|
|
391
|
+
stream=True,
|
|
392
|
+
**kwargs_copy
|
|
393
|
+
)
|
|
394
|
+
|
|
395
|
+
async for chunk in stream_gen:
|
|
396
|
+
# Yield the chunk for the caller
|
|
397
|
+
yield chunk
|
|
398
|
+
|
|
399
|
+
# Collect content for history
|
|
400
|
+
if hasattr(chunk, 'content') and chunk.content:
|
|
401
|
+
collected_content += chunk.content
|
|
402
|
+
|
|
403
|
+
# After streaming completes, add assistant message
|
|
404
|
+
if collected_content:
|
|
405
|
+
self.add_message('assistant', collected_content)
|
|
406
|
+
|
|
276
407
|
def _format_messages_for_provider(self) -> List[Dict[str, str]]:
|
|
277
408
|
"""Format messages for provider API"""
|
|
278
409
|
return [
|