abstractcore 2.6.8__tar.gz → 2.6.9__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.6.8 → abstractcore-2.6.9}/PKG-INFO +1 -45
- {abstractcore-2.6.8 → abstractcore-2.6.9}/README.md +0 -44
- {abstractcore-2.6.8 → abstractcore-2.6.9}/abstractcore/assets/model_capabilities.json +5 -14
- {abstractcore-2.6.8 → abstractcore-2.6.9}/abstractcore/processing/__init__.py +2 -2
- {abstractcore-2.6.8 → abstractcore-2.6.9}/abstractcore/processing/basic_summarizer.py +10 -79
- {abstractcore-2.6.8 → abstractcore-2.6.9}/abstractcore/providers/base.py +20 -23
- {abstractcore-2.6.8 → abstractcore-2.6.9}/abstractcore/server/app.py +2 -51
- abstractcore-2.6.9/abstractcore/tools/__init__.py +101 -0
- {abstractcore-2.6.8 → abstractcore-2.6.9}/abstractcore/tools/common_tools.py +15 -177
- {abstractcore-2.6.8 → abstractcore-2.6.9}/abstractcore/tools/parser.py +4 -96
- {abstractcore-2.6.8 → abstractcore-2.6.9}/abstractcore/tools/registry.py +16 -15
- {abstractcore-2.6.8 → abstractcore-2.6.9}/abstractcore/utils/version.py +1 -1
- {abstractcore-2.6.8 → abstractcore-2.6.9}/abstractcore.egg-info/PKG-INFO +1 -45
- abstractcore-2.6.8/abstractcore/tools/__init__.py +0 -122
- {abstractcore-2.6.8 → abstractcore-2.6.9}/LICENSE +0 -0
- {abstractcore-2.6.8 → abstractcore-2.6.9}/abstractcore/__init__.py +0 -0
- {abstractcore-2.6.8 → abstractcore-2.6.9}/abstractcore/apps/__init__.py +0 -0
- {abstractcore-2.6.8 → abstractcore-2.6.9}/abstractcore/apps/__main__.py +0 -0
- {abstractcore-2.6.8 → abstractcore-2.6.9}/abstractcore/apps/app_config_utils.py +0 -0
- {abstractcore-2.6.8 → abstractcore-2.6.9}/abstractcore/apps/deepsearch.py +0 -0
- {abstractcore-2.6.8 → abstractcore-2.6.9}/abstractcore/apps/extractor.py +0 -0
- {abstractcore-2.6.8 → abstractcore-2.6.9}/abstractcore/apps/intent.py +0 -0
- {abstractcore-2.6.8 → abstractcore-2.6.9}/abstractcore/apps/judge.py +0 -0
- {abstractcore-2.6.8 → abstractcore-2.6.9}/abstractcore/apps/summarizer.py +0 -0
- {abstractcore-2.6.8 → abstractcore-2.6.9}/abstractcore/architectures/__init__.py +0 -0
- {abstractcore-2.6.8 → abstractcore-2.6.9}/abstractcore/architectures/detection.py +0 -0
- {abstractcore-2.6.8 → abstractcore-2.6.9}/abstractcore/architectures/enums.py +0 -0
- {abstractcore-2.6.8 → abstractcore-2.6.9}/abstractcore/assets/architecture_formats.json +0 -0
- {abstractcore-2.6.8 → abstractcore-2.6.9}/abstractcore/assets/session_schema.json +0 -0
- {abstractcore-2.6.8 → abstractcore-2.6.9}/abstractcore/compression/__init__.py +0 -0
- {abstractcore-2.6.8 → abstractcore-2.6.9}/abstractcore/compression/analytics.py +0 -0
- {abstractcore-2.6.8 → abstractcore-2.6.9}/abstractcore/compression/cache.py +0 -0
- {abstractcore-2.6.8 → abstractcore-2.6.9}/abstractcore/compression/config.py +0 -0
- {abstractcore-2.6.8 → abstractcore-2.6.9}/abstractcore/compression/exceptions.py +0 -0
- {abstractcore-2.6.8 → abstractcore-2.6.9}/abstractcore/compression/glyph_processor.py +0 -0
- {abstractcore-2.6.8 → abstractcore-2.6.9}/abstractcore/compression/optimizer.py +0 -0
- {abstractcore-2.6.8 → abstractcore-2.6.9}/abstractcore/compression/orchestrator.py +0 -0
- {abstractcore-2.6.8 → abstractcore-2.6.9}/abstractcore/compression/pil_text_renderer.py +0 -0
- {abstractcore-2.6.8 → abstractcore-2.6.9}/abstractcore/compression/quality.py +0 -0
- {abstractcore-2.6.8 → abstractcore-2.6.9}/abstractcore/compression/text_formatter.py +0 -0
- {abstractcore-2.6.8 → abstractcore-2.6.9}/abstractcore/compression/vision_compressor.py +0 -0
- {abstractcore-2.6.8 → abstractcore-2.6.9}/abstractcore/config/__init__.py +0 -0
- {abstractcore-2.6.8 → abstractcore-2.6.9}/abstractcore/config/main.py +0 -0
- {abstractcore-2.6.8 → abstractcore-2.6.9}/abstractcore/config/manager.py +0 -0
- {abstractcore-2.6.8 → abstractcore-2.6.9}/abstractcore/config/vision_config.py +0 -0
- {abstractcore-2.6.8 → abstractcore-2.6.9}/abstractcore/core/__init__.py +0 -0
- {abstractcore-2.6.8 → abstractcore-2.6.9}/abstractcore/core/enums.py +0 -0
- {abstractcore-2.6.8 → abstractcore-2.6.9}/abstractcore/core/factory.py +0 -0
- {abstractcore-2.6.8 → abstractcore-2.6.9}/abstractcore/core/interface.py +0 -0
- {abstractcore-2.6.8 → abstractcore-2.6.9}/abstractcore/core/retry.py +0 -0
- {abstractcore-2.6.8 → abstractcore-2.6.9}/abstractcore/core/session.py +0 -0
- {abstractcore-2.6.8 → abstractcore-2.6.9}/abstractcore/core/types.py +0 -0
- {abstractcore-2.6.8 → abstractcore-2.6.9}/abstractcore/download.py +0 -0
- {abstractcore-2.6.8 → abstractcore-2.6.9}/abstractcore/embeddings/__init__.py +0 -0
- {abstractcore-2.6.8 → abstractcore-2.6.9}/abstractcore/embeddings/manager.py +0 -0
- {abstractcore-2.6.8 → abstractcore-2.6.9}/abstractcore/embeddings/models.py +0 -0
- {abstractcore-2.6.8 → abstractcore-2.6.9}/abstractcore/events/__init__.py +0 -0
- {abstractcore-2.6.8 → abstractcore-2.6.9}/abstractcore/exceptions/__init__.py +0 -0
- {abstractcore-2.6.8 → abstractcore-2.6.9}/abstractcore/media/__init__.py +0 -0
- {abstractcore-2.6.8 → abstractcore-2.6.9}/abstractcore/media/auto_handler.py +0 -0
- {abstractcore-2.6.8 → abstractcore-2.6.9}/abstractcore/media/base.py +0 -0
- {abstractcore-2.6.8 → abstractcore-2.6.9}/abstractcore/media/capabilities.py +0 -0
- {abstractcore-2.6.8 → abstractcore-2.6.9}/abstractcore/media/handlers/__init__.py +0 -0
- {abstractcore-2.6.8 → abstractcore-2.6.9}/abstractcore/media/handlers/anthropic_handler.py +0 -0
- {abstractcore-2.6.8 → abstractcore-2.6.9}/abstractcore/media/handlers/local_handler.py +0 -0
- {abstractcore-2.6.8 → abstractcore-2.6.9}/abstractcore/media/handlers/openai_handler.py +0 -0
- {abstractcore-2.6.8 → abstractcore-2.6.9}/abstractcore/media/processors/__init__.py +0 -0
- {abstractcore-2.6.8 → abstractcore-2.6.9}/abstractcore/media/processors/direct_pdf_processor.py +0 -0
- {abstractcore-2.6.8 → abstractcore-2.6.9}/abstractcore/media/processors/glyph_pdf_processor.py +0 -0
- {abstractcore-2.6.8 → abstractcore-2.6.9}/abstractcore/media/processors/image_processor.py +0 -0
- {abstractcore-2.6.8 → abstractcore-2.6.9}/abstractcore/media/processors/office_processor.py +0 -0
- {abstractcore-2.6.8 → abstractcore-2.6.9}/abstractcore/media/processors/pdf_processor.py +0 -0
- {abstractcore-2.6.8 → abstractcore-2.6.9}/abstractcore/media/processors/text_processor.py +0 -0
- {abstractcore-2.6.8 → abstractcore-2.6.9}/abstractcore/media/types.py +0 -0
- {abstractcore-2.6.8 → abstractcore-2.6.9}/abstractcore/media/utils/__init__.py +0 -0
- {abstractcore-2.6.8 → abstractcore-2.6.9}/abstractcore/media/utils/image_scaler.py +0 -0
- {abstractcore-2.6.8 → abstractcore-2.6.9}/abstractcore/media/vision_fallback.py +0 -0
- {abstractcore-2.6.8 → abstractcore-2.6.9}/abstractcore/processing/basic_deepsearch.py +0 -0
- {abstractcore-2.6.8 → abstractcore-2.6.9}/abstractcore/processing/basic_extractor.py +0 -0
- {abstractcore-2.6.8 → abstractcore-2.6.9}/abstractcore/processing/basic_intent.py +0 -0
- {abstractcore-2.6.8 → abstractcore-2.6.9}/abstractcore/processing/basic_judge.py +0 -0
- {abstractcore-2.6.8 → abstractcore-2.6.9}/abstractcore/providers/__init__.py +0 -0
- {abstractcore-2.6.8 → abstractcore-2.6.9}/abstractcore/providers/anthropic_provider.py +0 -0
- {abstractcore-2.6.8 → abstractcore-2.6.9}/abstractcore/providers/huggingface_provider.py +0 -0
- {abstractcore-2.6.8 → abstractcore-2.6.9}/abstractcore/providers/lmstudio_provider.py +0 -0
- {abstractcore-2.6.8 → abstractcore-2.6.9}/abstractcore/providers/mlx_provider.py +0 -0
- {abstractcore-2.6.8 → abstractcore-2.6.9}/abstractcore/providers/model_capabilities.py +0 -0
- {abstractcore-2.6.8 → abstractcore-2.6.9}/abstractcore/providers/ollama_provider.py +0 -0
- {abstractcore-2.6.8 → abstractcore-2.6.9}/abstractcore/providers/openai_compatible_provider.py +0 -0
- {abstractcore-2.6.8 → abstractcore-2.6.9}/abstractcore/providers/openai_provider.py +0 -0
- {abstractcore-2.6.8 → abstractcore-2.6.9}/abstractcore/providers/registry.py +0 -0
- {abstractcore-2.6.8 → abstractcore-2.6.9}/abstractcore/providers/streaming.py +0 -0
- {abstractcore-2.6.8 → abstractcore-2.6.9}/abstractcore/providers/vllm_provider.py +0 -0
- {abstractcore-2.6.8 → abstractcore-2.6.9}/abstractcore/server/__init__.py +0 -0
- {abstractcore-2.6.8 → abstractcore-2.6.9}/abstractcore/structured/__init__.py +0 -0
- {abstractcore-2.6.8 → abstractcore-2.6.9}/abstractcore/structured/handler.py +0 -0
- {abstractcore-2.6.8 → abstractcore-2.6.9}/abstractcore/structured/retry.py +0 -0
- {abstractcore-2.6.8 → abstractcore-2.6.9}/abstractcore/tools/core.py +0 -0
- {abstractcore-2.6.8 → abstractcore-2.6.9}/abstractcore/tools/handler.py +0 -0
- {abstractcore-2.6.8 → abstractcore-2.6.9}/abstractcore/tools/syntax_rewriter.py +0 -0
- {abstractcore-2.6.8 → abstractcore-2.6.9}/abstractcore/tools/tag_rewriter.py +0 -0
- {abstractcore-2.6.8 → abstractcore-2.6.9}/abstractcore/utils/__init__.py +0 -0
- {abstractcore-2.6.8 → abstractcore-2.6.9}/abstractcore/utils/cli.py +0 -0
- {abstractcore-2.6.8 → abstractcore-2.6.9}/abstractcore/utils/message_preprocessor.py +0 -0
- {abstractcore-2.6.8 → abstractcore-2.6.9}/abstractcore/utils/self_fixes.py +0 -0
- {abstractcore-2.6.8 → abstractcore-2.6.9}/abstractcore/utils/structured_logging.py +0 -0
- {abstractcore-2.6.8 → abstractcore-2.6.9}/abstractcore/utils/token_utils.py +0 -0
- {abstractcore-2.6.8 → abstractcore-2.6.9}/abstractcore/utils/trace_export.py +0 -0
- {abstractcore-2.6.8 → abstractcore-2.6.9}/abstractcore/utils/vlm_token_calculator.py +0 -0
- {abstractcore-2.6.8 → abstractcore-2.6.9}/abstractcore.egg-info/SOURCES.txt +0 -0
- {abstractcore-2.6.8 → abstractcore-2.6.9}/abstractcore.egg-info/dependency_links.txt +0 -0
- {abstractcore-2.6.8 → abstractcore-2.6.9}/abstractcore.egg-info/entry_points.txt +0 -0
- {abstractcore-2.6.8 → abstractcore-2.6.9}/abstractcore.egg-info/requires.txt +0 -0
- {abstractcore-2.6.8 → abstractcore-2.6.9}/abstractcore.egg-info/top_level.txt +0 -0
- {abstractcore-2.6.8 → abstractcore-2.6.9}/pyproject.toml +0 -0
- {abstractcore-2.6.8 → abstractcore-2.6.9}/setup.cfg +0 -0
- {abstractcore-2.6.8 → abstractcore-2.6.9}/tests/test_agentic_cli_compatibility.py +0 -0
- {abstractcore-2.6.8 → abstractcore-2.6.9}/tests/test_basic_session.py +0 -0
- {abstractcore-2.6.8 → abstractcore-2.6.9}/tests/test_complete_integration.py +0 -0
- {abstractcore-2.6.8 → abstractcore-2.6.9}/tests/test_comprehensive_events.py +0 -0
- {abstractcore-2.6.8 → abstractcore-2.6.9}/tests/test_core_components.py +0 -0
- {abstractcore-2.6.8 → abstractcore-2.6.9}/tests/test_enhanced_prompt.py +0 -0
- {abstractcore-2.6.8 → abstractcore-2.6.9}/tests/test_environment_variable_tool_call_tags.py +0 -0
- {abstractcore-2.6.8 → abstractcore-2.6.9}/tests/test_factory.py +0 -0
- {abstractcore-2.6.8 → abstractcore-2.6.9}/tests/test_final_accuracy.py +0 -0
- {abstractcore-2.6.8 → abstractcore-2.6.9}/tests/test_final_comprehensive.py +0 -0
- {abstractcore-2.6.8 → abstractcore-2.6.9}/tests/test_final_graceful_errors.py +0 -0
- {abstractcore-2.6.8 → abstractcore-2.6.9}/tests/test_graceful_fallback.py +0 -0
- {abstractcore-2.6.8 → abstractcore-2.6.9}/tests/test_import_debug.py +0 -0
- {abstractcore-2.6.8 → abstractcore-2.6.9}/tests/test_integrated_functionality.py +0 -0
- {abstractcore-2.6.8 → abstractcore-2.6.9}/tests/test_retry_observability.py +0 -0
- {abstractcore-2.6.8 → abstractcore-2.6.9}/tests/test_retry_strategy.py +0 -0
- {abstractcore-2.6.8 → abstractcore-2.6.9}/tests/test_seed_determinism.py +0 -0
- {abstractcore-2.6.8 → abstractcore-2.6.9}/tests/test_seed_temperature_basic.py +0 -0
- {abstractcore-2.6.8 → abstractcore-2.6.9}/tests/test_sensory_prompting.py +0 -0
- {abstractcore-2.6.8 → abstractcore-2.6.9}/tests/test_text_only_model_experience.py +0 -0
- {abstractcore-2.6.8 → abstractcore-2.6.9}/tests/test_unload_memory.py +0 -0
- {abstractcore-2.6.8 → abstractcore-2.6.9}/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.6.
|
|
3
|
+
Version: 2.6.9
|
|
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>
|
|
@@ -195,50 +195,6 @@ response = llm.generate(
|
|
|
195
195
|
print(response.content)
|
|
196
196
|
```
|
|
197
197
|
|
|
198
|
-
### Tool Execution Modes
|
|
199
|
-
|
|
200
|
-
AbstractCore supports two tool execution modes:
|
|
201
|
-
|
|
202
|
-
**Mode 1: Passthrough (Default)** - Returns raw tool call tags for downstream processing
|
|
203
|
-
|
|
204
|
-
```python
|
|
205
|
-
from abstractcore import create_llm
|
|
206
|
-
from abstractcore.tools import tool
|
|
207
|
-
|
|
208
|
-
@tool(name="get_weather", description="Get weather for a city")
|
|
209
|
-
def get_weather(city: str) -> str:
|
|
210
|
-
return f"Weather in {city}: Sunny, 22°C"
|
|
211
|
-
|
|
212
|
-
llm = create_llm("ollama", model="qwen3:4b") # execute_tools=False by default
|
|
213
|
-
response = llm.generate("What's the weather in Paris?", tools=[get_weather])
|
|
214
|
-
# response.content contains raw tool call tags: <|tool_call|>...
|
|
215
|
-
# Downstream runtime (AbstractRuntime, Codex, Claude Code) parses and executes
|
|
216
|
-
```
|
|
217
|
-
|
|
218
|
-
**Use case**: Agent loops, AbstractRuntime, Codex, Claude Code, custom orchestration
|
|
219
|
-
|
|
220
|
-
**Mode 2: Direct Execution** - AbstractCore executes tools and returns results
|
|
221
|
-
|
|
222
|
-
```python
|
|
223
|
-
from abstractcore import create_llm
|
|
224
|
-
from abstractcore.tools import tool
|
|
225
|
-
from abstractcore.tools.registry import register_tool
|
|
226
|
-
|
|
227
|
-
@tool(name="get_weather", description="Get weather for a city")
|
|
228
|
-
def get_weather(city: str) -> str:
|
|
229
|
-
return f"Weather in {city}: Sunny, 22°C"
|
|
230
|
-
|
|
231
|
-
register_tool(get_weather) # Required for direct execution
|
|
232
|
-
|
|
233
|
-
llm = create_llm("ollama", model="qwen3:4b", execute_tools=True)
|
|
234
|
-
response = llm.generate("What's the weather in Paris?", tools=[get_weather])
|
|
235
|
-
# response.content contains executed tool results
|
|
236
|
-
```
|
|
237
|
-
|
|
238
|
-
**Use case**: Simple scripts, single-turn tool use
|
|
239
|
-
|
|
240
|
-
> **Note**: The `@tool` decorator creates metadata but does NOT register globally. Tools are passed explicitly to `generate()`. Use `register_tool()` only when using direct execution mode.
|
|
241
|
-
|
|
242
198
|
### Response Object (GenerateResponse)
|
|
243
199
|
|
|
244
200
|
Every LLM generation returns a **GenerateResponse** object with consistent structure across all providers:
|
|
@@ -65,50 +65,6 @@ response = llm.generate(
|
|
|
65
65
|
print(response.content)
|
|
66
66
|
```
|
|
67
67
|
|
|
68
|
-
### Tool Execution Modes
|
|
69
|
-
|
|
70
|
-
AbstractCore supports two tool execution modes:
|
|
71
|
-
|
|
72
|
-
**Mode 1: Passthrough (Default)** - Returns raw tool call tags for downstream processing
|
|
73
|
-
|
|
74
|
-
```python
|
|
75
|
-
from abstractcore import create_llm
|
|
76
|
-
from abstractcore.tools import tool
|
|
77
|
-
|
|
78
|
-
@tool(name="get_weather", description="Get weather for a city")
|
|
79
|
-
def get_weather(city: str) -> str:
|
|
80
|
-
return f"Weather in {city}: Sunny, 22°C"
|
|
81
|
-
|
|
82
|
-
llm = create_llm("ollama", model="qwen3:4b") # execute_tools=False by default
|
|
83
|
-
response = llm.generate("What's the weather in Paris?", tools=[get_weather])
|
|
84
|
-
# response.content contains raw tool call tags: <|tool_call|>...
|
|
85
|
-
# Downstream runtime (AbstractRuntime, Codex, Claude Code) parses and executes
|
|
86
|
-
```
|
|
87
|
-
|
|
88
|
-
**Use case**: Agent loops, AbstractRuntime, Codex, Claude Code, custom orchestration
|
|
89
|
-
|
|
90
|
-
**Mode 2: Direct Execution** - AbstractCore executes tools and returns results
|
|
91
|
-
|
|
92
|
-
```python
|
|
93
|
-
from abstractcore import create_llm
|
|
94
|
-
from abstractcore.tools import tool
|
|
95
|
-
from abstractcore.tools.registry import register_tool
|
|
96
|
-
|
|
97
|
-
@tool(name="get_weather", description="Get weather for a city")
|
|
98
|
-
def get_weather(city: str) -> str:
|
|
99
|
-
return f"Weather in {city}: Sunny, 22°C"
|
|
100
|
-
|
|
101
|
-
register_tool(get_weather) # Required for direct execution
|
|
102
|
-
|
|
103
|
-
llm = create_llm("ollama", model="qwen3:4b", execute_tools=True)
|
|
104
|
-
response = llm.generate("What's the weather in Paris?", tools=[get_weather])
|
|
105
|
-
# response.content contains executed tool results
|
|
106
|
-
```
|
|
107
|
-
|
|
108
|
-
**Use case**: Simple scripts, single-turn tool use
|
|
109
|
-
|
|
110
|
-
> **Note**: The `@tool` decorator creates metadata but does NOT register globally. Tools are passed explicitly to `generate()`. Use `register_tool()` only when using direct execution mode.
|
|
111
|
-
|
|
112
68
|
### Response Object (GenerateResponse)
|
|
113
69
|
|
|
114
70
|
Every LLM generation returns a **GenerateResponse** object with consistent structure across all providers:
|
|
@@ -638,26 +638,17 @@
|
|
|
638
638
|
"max_tokens": 262144
|
|
639
639
|
},
|
|
640
640
|
"qwen3-coder-30b": {
|
|
641
|
-
"max_output_tokens":
|
|
641
|
+
"max_output_tokens": 8192,
|
|
642
642
|
"tool_support": "native",
|
|
643
643
|
"structured_output": "native",
|
|
644
644
|
"parallel_tools": true,
|
|
645
645
|
"vision_support": false,
|
|
646
646
|
"audio_support": false,
|
|
647
|
-
"
|
|
648
|
-
"
|
|
649
|
-
"active_parameters": "3.3B",
|
|
650
|
-
"experts": 128,
|
|
651
|
-
"experts_activated": 8,
|
|
652
|
-
"notes": "Code-focused MoE model (30.5B total/3.3B active, 128 experts/8 activated). Native tool support via chatml-function-calling format. Supports up to 1M tokens with YaRN extension.",
|
|
653
|
-
"source": "Qwen HuggingFace model card 2025",
|
|
647
|
+
"notes": "Code-focused model with native tool support via chatml-function-calling format",
|
|
648
|
+
"source": "Alibaba official docs",
|
|
654
649
|
"canonical_name": "qwen3-coder-30b",
|
|
655
|
-
"aliases": [
|
|
656
|
-
|
|
657
|
-
"qwen3-coder-30b-a3b",
|
|
658
|
-
"qwen3-coder-30b-a3b-instruct"
|
|
659
|
-
],
|
|
660
|
-
"max_tokens": 262144
|
|
650
|
+
"aliases": [],
|
|
651
|
+
"max_tokens": 32768
|
|
661
652
|
},
|
|
662
653
|
"qwen2-vl": {
|
|
663
654
|
"max_output_tokens": 8192,
|
|
@@ -5,14 +5,14 @@ Basic text processing capabilities built on top of AbstractCore,
|
|
|
5
5
|
demonstrating how to leverage the core infrastructure for real-world tasks.
|
|
6
6
|
"""
|
|
7
7
|
|
|
8
|
-
from .basic_summarizer import BasicSummarizer, SummaryStyle, SummaryLength
|
|
8
|
+
from .basic_summarizer import BasicSummarizer, SummaryStyle, SummaryLength
|
|
9
9
|
from .basic_extractor import BasicExtractor
|
|
10
10
|
from .basic_judge import BasicJudge, JudgmentCriteria, Assessment, create_judge
|
|
11
11
|
from .basic_deepsearch import BasicDeepSearch, ResearchReport, ResearchFinding, ResearchPlan, ResearchSubTask
|
|
12
12
|
from .basic_intent import BasicIntentAnalyzer, IntentType, IntentDepth, IntentContext, IdentifiedIntent, IntentAnalysisOutput
|
|
13
13
|
|
|
14
14
|
__all__ = [
|
|
15
|
-
'BasicSummarizer', 'SummaryStyle', 'SummaryLength',
|
|
15
|
+
'BasicSummarizer', 'SummaryStyle', 'SummaryLength',
|
|
16
16
|
'BasicExtractor',
|
|
17
17
|
'BasicJudge', 'JudgmentCriteria', 'Assessment', 'create_judge',
|
|
18
18
|
'BasicDeepSearch', 'ResearchReport', 'ResearchFinding', 'ResearchPlan', 'ResearchSubTask',
|
|
@@ -35,42 +35,6 @@ class SummaryLength(Enum):
|
|
|
35
35
|
COMPREHENSIVE = "comprehensive" # Full analysis with context
|
|
36
36
|
|
|
37
37
|
|
|
38
|
-
class CompressionMode(Enum):
|
|
39
|
-
"""Compression aggressiveness for chat history summarization.
|
|
40
|
-
|
|
41
|
-
Controls how aggressively the summarizer compresses conversation history:
|
|
42
|
-
- LIGHT: Keep most information, only remove redundancy
|
|
43
|
-
- STANDARD: Balanced compression, main points and context
|
|
44
|
-
- HEAVY: Aggressive compression, only critical information
|
|
45
|
-
"""
|
|
46
|
-
LIGHT = "light"
|
|
47
|
-
STANDARD = "standard"
|
|
48
|
-
HEAVY = "heavy"
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
# Compression mode-specific instructions for summarization prompts
|
|
52
|
-
COMPRESSION_INSTRUCTIONS = {
|
|
53
|
-
CompressionMode.LIGHT: (
|
|
54
|
-
"Preserve most details from this conversation while removing only redundancy. "
|
|
55
|
-
"Keep: all key decisions and outcomes, important context and background, "
|
|
56
|
-
"specific details/names/numbers/technical terms, all tool calls and results, "
|
|
57
|
-
"error messages and resolutions. Remove only: repetitive greetings, duplicate information."
|
|
58
|
-
),
|
|
59
|
-
CompressionMode.STANDARD: (
|
|
60
|
-
"Summarize with balanced compression, keeping main points and essential context. "
|
|
61
|
-
"Keep: key decisions and rationale, important outcomes, critical context for ongoing work, "
|
|
62
|
-
"unresolved items and pending tasks. Remove: intermediate reasoning steps, "
|
|
63
|
-
"exploratory tangents, detailed tool outputs (keep only key findings)."
|
|
64
|
-
),
|
|
65
|
-
CompressionMode.HEAVY: (
|
|
66
|
-
"Extract only the most critical information. Keep ONLY: final decisions made, "
|
|
67
|
-
"critical outcomes (success/failure), essential context to continue work, "
|
|
68
|
-
"blocking issues and hard dependencies. Remove: all exploratory discussion, "
|
|
69
|
-
"all intermediate steps, all detailed outputs, all background explanations."
|
|
70
|
-
),
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
|
|
74
38
|
class LLMSummaryOutput(BaseModel):
|
|
75
39
|
"""LLM-generated summary output (without word counts)"""
|
|
76
40
|
summary: str = Field(description="The main summary text")
|
|
@@ -529,8 +493,7 @@ Create a unified summary that represents the entire document effectively."""
|
|
|
529
493
|
self,
|
|
530
494
|
messages: List[dict],
|
|
531
495
|
preserve_recent: int = 6,
|
|
532
|
-
focus: Optional[str] = None
|
|
533
|
-
compression_mode: CompressionMode = CompressionMode.STANDARD
|
|
496
|
+
focus: Optional[str] = None
|
|
534
497
|
) -> SummaryOutput:
|
|
535
498
|
"""
|
|
536
499
|
Specialized method for chat history summarization following SOTA 2025 practices
|
|
@@ -539,7 +502,6 @@ Create a unified summary that represents the entire document effectively."""
|
|
|
539
502
|
messages: List of message dicts with 'role' and 'content' keys
|
|
540
503
|
preserve_recent: Number of recent messages to keep intact (default 6)
|
|
541
504
|
focus: Optional focus for summarization (e.g., "key decisions", "technical solutions")
|
|
542
|
-
compression_mode: How aggressively to compress (LIGHT, STANDARD, HEAVY)
|
|
543
505
|
|
|
544
506
|
Returns:
|
|
545
507
|
SummaryOutput: Structured summary optimized for chat history context
|
|
@@ -549,67 +511,36 @@ Create a unified summary that represents the entire document effectively."""
|
|
|
549
511
|
- Focuses on decisions, solutions, and ongoing topics
|
|
550
512
|
- Maintains user intent and assistant responses
|
|
551
513
|
- Optimized for chat continuation rather than standalone summary
|
|
552
|
-
|
|
553
|
-
Compression Modes:
|
|
554
|
-
- LIGHT: Keep most information, only remove redundancy
|
|
555
|
-
- STANDARD: Balanced compression, main points and context
|
|
556
|
-
- HEAVY: Aggressive compression, only critical information
|
|
557
514
|
"""
|
|
558
|
-
# Build focus with compression instructions
|
|
559
|
-
compression_instruction = COMPRESSION_INSTRUCTIONS.get(
|
|
560
|
-
compression_mode,
|
|
561
|
-
COMPRESSION_INSTRUCTIONS[CompressionMode.STANDARD]
|
|
562
|
-
)
|
|
563
|
-
|
|
564
|
-
# Combine user focus with compression instruction
|
|
565
|
-
if focus:
|
|
566
|
-
effective_focus = f"{compression_instruction} Focus especially on: {focus}"
|
|
567
|
-
else:
|
|
568
|
-
effective_focus = compression_instruction
|
|
569
|
-
|
|
570
|
-
# Map compression mode to summary length for appropriate output size
|
|
571
|
-
length_map = {
|
|
572
|
-
CompressionMode.LIGHT: SummaryLength.DETAILED,
|
|
573
|
-
CompressionMode.STANDARD: SummaryLength.STANDARD,
|
|
574
|
-
CompressionMode.HEAVY: SummaryLength.BRIEF,
|
|
575
|
-
}
|
|
576
|
-
target_length = length_map.get(compression_mode, SummaryLength.STANDARD)
|
|
577
|
-
|
|
578
|
-
logger.debug("Chat history summarization with compression mode",
|
|
579
|
-
message_count=len(messages),
|
|
580
|
-
preserve_recent=preserve_recent,
|
|
581
|
-
compression_mode=compression_mode.value,
|
|
582
|
-
target_length=target_length.value)
|
|
583
|
-
|
|
584
515
|
if len(messages) <= preserve_recent:
|
|
585
516
|
# If short enough, just summarize normally
|
|
586
|
-
logger.debug("Chat history is short, using standard summarization",
|
|
587
|
-
message_count=len(messages),
|
|
517
|
+
logger.debug("Chat history is short, using standard summarization",
|
|
518
|
+
message_count=len(messages),
|
|
588
519
|
preserve_recent=preserve_recent)
|
|
589
520
|
chat_text = self._format_chat_messages_to_text(messages)
|
|
590
521
|
return self.summarize(
|
|
591
522
|
chat_text,
|
|
592
|
-
focus=
|
|
523
|
+
focus=focus or "conversational context and key information",
|
|
593
524
|
style=SummaryStyle.CONVERSATIONAL,
|
|
594
|
-
length=
|
|
525
|
+
length=SummaryLength.STANDARD
|
|
595
526
|
)
|
|
596
527
|
|
|
597
528
|
# Split into older messages (to summarize) and recent messages (to preserve)
|
|
598
529
|
older_messages = messages[:-preserve_recent]
|
|
599
530
|
recent_messages = messages[-preserve_recent:]
|
|
600
|
-
|
|
601
|
-
logger.debug("Splitting chat history for summarization",
|
|
531
|
+
|
|
532
|
+
logger.debug("Splitting chat history for summarization",
|
|
602
533
|
total_messages=len(messages),
|
|
603
534
|
older_messages=len(older_messages),
|
|
604
535
|
recent_messages=len(recent_messages))
|
|
605
536
|
|
|
606
|
-
# Summarize older messages with conversational focus
|
|
537
|
+
# Summarize older messages with conversational focus
|
|
607
538
|
older_text = self._format_chat_messages_to_text(older_messages)
|
|
608
539
|
older_summary = self.summarize(
|
|
609
540
|
older_text,
|
|
610
|
-
focus=
|
|
541
|
+
focus=focus or "key decisions, solutions, and ongoing context",
|
|
611
542
|
style=SummaryStyle.CONVERSATIONAL,
|
|
612
|
-
length=
|
|
543
|
+
length=SummaryLength.DETAILED
|
|
613
544
|
)
|
|
614
545
|
|
|
615
546
|
# The summary should ONLY contain the older messages summary
|
|
@@ -5,7 +5,6 @@ Base provider with integrated telemetry, events, and exception handling.
|
|
|
5
5
|
import time
|
|
6
6
|
import uuid
|
|
7
7
|
import asyncio
|
|
8
|
-
import warnings
|
|
9
8
|
from collections import deque
|
|
10
9
|
from typing import List, Dict, Any, Optional, Union, Iterator, AsyncIterator, Type
|
|
11
10
|
from abc import ABC, abstractmethod
|
|
@@ -61,13 +60,6 @@ class BaseProvider(AbstractCoreInterface, ABC):
|
|
|
61
60
|
# execute_tools: True = AbstractCore executes tools (legacy mode)
|
|
62
61
|
# False = Pass-through mode (default - for API server / agentic CLI)
|
|
63
62
|
self.execute_tools = kwargs.get('execute_tools', False)
|
|
64
|
-
if self.execute_tools:
|
|
65
|
-
warnings.warn(
|
|
66
|
-
"execute_tools=True is deprecated. Prefer passing tools explicitly to generate() "
|
|
67
|
-
"and executing tool calls in the host/runtime via a ToolExecutor.",
|
|
68
|
-
DeprecationWarning,
|
|
69
|
-
stacklevel=2,
|
|
70
|
-
)
|
|
71
63
|
|
|
72
64
|
# Setup retry manager with optional configuration
|
|
73
65
|
retry_config = kwargs.get('retry_config', None)
|
|
@@ -210,12 +202,6 @@ class BaseProvider(AbstractCoreInterface, ABC):
|
|
|
210
202
|
"""
|
|
211
203
|
trace_id = str(uuid.uuid4())
|
|
212
204
|
|
|
213
|
-
# If trace retention is disabled, still return a trace_id for correlation
|
|
214
|
-
# without constructing/storing a full trace payload.
|
|
215
|
-
maxlen = getattr(getattr(self, "_traces", None), "maxlen", None)
|
|
216
|
-
if maxlen == 0:
|
|
217
|
-
return trace_id
|
|
218
|
-
|
|
219
205
|
# Extract generation parameters
|
|
220
206
|
temperature = kwargs.get('temperature', self.temperature)
|
|
221
207
|
max_tokens = kwargs.get('max_tokens', self.max_tokens)
|
|
@@ -422,13 +408,6 @@ class BaseProvider(AbstractCoreInterface, ABC):
|
|
|
422
408
|
|
|
423
409
|
# Handle tool execution control
|
|
424
410
|
should_execute_tools = execute_tools if execute_tools is not None else self.execute_tools
|
|
425
|
-
if should_execute_tools and converted_tools:
|
|
426
|
-
warnings.warn(
|
|
427
|
-
"execute_tools=True is deprecated. Prefer passing tools explicitly to generate() "
|
|
428
|
-
"and executing tool calls in the host/runtime via a ToolExecutor.",
|
|
429
|
-
DeprecationWarning,
|
|
430
|
-
stacklevel=2,
|
|
431
|
-
)
|
|
432
411
|
if not should_execute_tools and converted_tools:
|
|
433
412
|
# If tools are provided but execution is disabled,
|
|
434
413
|
# we still pass them to the provider for generation but won't execute them
|
|
@@ -1511,10 +1490,28 @@ Please provide a structured response."""
|
|
|
1511
1490
|
Returns:
|
|
1512
1491
|
GenerateResponse, AsyncIterator[GenerateResponse] for streaming, or BaseModel for structured output
|
|
1513
1492
|
"""
|
|
1514
|
-
|
|
1493
|
+
response = await self._agenerate_internal(
|
|
1515
1494
|
prompt, messages, system_prompt, tools, media, stream, **kwargs
|
|
1516
1495
|
)
|
|
1517
1496
|
|
|
1497
|
+
# Capture interaction trace if enabled (match sync generate_with_telemetry behavior)
|
|
1498
|
+
# Only for non-streaming responses that are GenerateResponse objects
|
|
1499
|
+
if not stream and self.enable_tracing and response and isinstance(response, GenerateResponse):
|
|
1500
|
+
trace_id = self._capture_trace(
|
|
1501
|
+
prompt=prompt,
|
|
1502
|
+
messages=messages,
|
|
1503
|
+
system_prompt=system_prompt,
|
|
1504
|
+
tools=tools,
|
|
1505
|
+
response=response,
|
|
1506
|
+
kwargs=kwargs
|
|
1507
|
+
)
|
|
1508
|
+
# Attach trace_id to response metadata
|
|
1509
|
+
if not response.metadata:
|
|
1510
|
+
response.metadata = {}
|
|
1511
|
+
response.metadata['trace_id'] = trace_id
|
|
1512
|
+
|
|
1513
|
+
return response
|
|
1514
|
+
|
|
1518
1515
|
async def _agenerate_internal(self,
|
|
1519
1516
|
prompt: str,
|
|
1520
1517
|
messages: Optional[List[Dict]],
|
|
@@ -1577,4 +1574,4 @@ Please provide a structured response."""
|
|
|
1577
1574
|
# Yield chunks asynchronously
|
|
1578
1575
|
for chunk in sync_gen:
|
|
1579
1576
|
yield chunk
|
|
1580
|
-
await asyncio.sleep(0) # Yield control to event loop
|
|
1577
|
+
await asyncio.sleep(0) # Yield control to event loop
|
|
@@ -1956,39 +1956,6 @@ async def provider_chat_completions(
|
|
|
1956
1956
|
_, model = parse_model_string(request.model)
|
|
1957
1957
|
return await process_chat_completion(provider, model, request, http_request)
|
|
1958
1958
|
|
|
1959
|
-
|
|
1960
|
-
def _extract_trace_metadata(http_request: Request) -> Dict[str, Any]:
|
|
1961
|
-
"""Extract trace metadata from request headers (schema-safe)."""
|
|
1962
|
-
meta: Dict[str, Any] = {}
|
|
1963
|
-
|
|
1964
|
-
raw = (
|
|
1965
|
-
http_request.headers.get("x-abstractcore-trace-metadata")
|
|
1966
|
-
or http_request.headers.get("x-abstract-trace-metadata")
|
|
1967
|
-
)
|
|
1968
|
-
if raw:
|
|
1969
|
-
try:
|
|
1970
|
-
parsed = json.loads(raw)
|
|
1971
|
-
if isinstance(parsed, dict):
|
|
1972
|
-
meta.update(parsed)
|
|
1973
|
-
except Exception:
|
|
1974
|
-
# Ignore invalid metadata payloads; tracing is best-effort.
|
|
1975
|
-
pass
|
|
1976
|
-
|
|
1977
|
-
header_map = {
|
|
1978
|
-
"actor_id": "x-abstractcore-actor-id",
|
|
1979
|
-
"session_id": "x-abstractcore-session-id",
|
|
1980
|
-
"run_id": "x-abstractcore-run-id",
|
|
1981
|
-
"parent_run_id": "x-abstractcore-parent-run-id",
|
|
1982
|
-
}
|
|
1983
|
-
for key, header in header_map.items():
|
|
1984
|
-
val = http_request.headers.get(header)
|
|
1985
|
-
if val is not None and key not in meta:
|
|
1986
|
-
meta[key] = val
|
|
1987
|
-
|
|
1988
|
-
# Never log or return these directly; they are for internal correlation only.
|
|
1989
|
-
return meta
|
|
1990
|
-
|
|
1991
|
-
|
|
1992
1959
|
async def process_chat_completion(
|
|
1993
1960
|
provider: str,
|
|
1994
1961
|
model: str,
|
|
@@ -2052,11 +2019,6 @@ async def process_chat_completion(
|
|
|
2052
2019
|
# Create LLM instance
|
|
2053
2020
|
# Prepare provider-specific kwargs
|
|
2054
2021
|
provider_kwargs = {}
|
|
2055
|
-
trace_metadata = _extract_trace_metadata(http_request)
|
|
2056
|
-
if trace_metadata:
|
|
2057
|
-
# Enable trace capture (trace_id) without retaining full trace buffers by default.
|
|
2058
|
-
provider_kwargs["enable_tracing"] = True
|
|
2059
|
-
provider_kwargs.setdefault("max_traces", 0)
|
|
2060
2022
|
if request.base_url:
|
|
2061
2023
|
provider_kwargs["base_url"] = request.base_url
|
|
2062
2024
|
logger.info(
|
|
@@ -2085,8 +2047,6 @@ async def process_chat_completion(
|
|
|
2085
2047
|
"tool_choice": request.tool_choice if request.tools else None,
|
|
2086
2048
|
"execute_tools": False, # Server mode - don't execute tools
|
|
2087
2049
|
}
|
|
2088
|
-
if trace_metadata:
|
|
2089
|
-
gen_kwargs["trace_metadata"] = trace_metadata
|
|
2090
2050
|
|
|
2091
2051
|
# Add optional parameters
|
|
2092
2052
|
if request.stop:
|
|
@@ -2121,18 +2081,9 @@ async def process_chat_completion(
|
|
|
2121
2081
|
)
|
|
2122
2082
|
else:
|
|
2123
2083
|
response = llm.generate(**gen_kwargs)
|
|
2124
|
-
|
|
2084
|
+
return convert_to_openai_response(
|
|
2125
2085
|
response, provider, model, syntax_rewriter, request_id
|
|
2126
2086
|
)
|
|
2127
|
-
trace_id = None
|
|
2128
|
-
if hasattr(response, "metadata") and isinstance(getattr(response, "metadata"), dict):
|
|
2129
|
-
trace_id = response.metadata.get("trace_id")
|
|
2130
|
-
if trace_id:
|
|
2131
|
-
return JSONResponse(
|
|
2132
|
-
content=openai_response,
|
|
2133
|
-
headers={"X-AbstractCore-Trace-Id": str(trace_id)},
|
|
2134
|
-
)
|
|
2135
|
-
return openai_response
|
|
2136
2087
|
finally:
|
|
2137
2088
|
# Cleanup temporary files (base64 and downloaded images) with delay to avoid race conditions
|
|
2138
2089
|
import threading
|
|
@@ -2457,4 +2408,4 @@ Debug Mode:
|
|
|
2457
2408
|
# ============================================================================
|
|
2458
2409
|
|
|
2459
2410
|
if __name__ == "__main__":
|
|
2460
|
-
run_server_with_args()
|
|
2411
|
+
run_server_with_args()
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Universal tool support for AbstractCore.
|
|
3
|
+
|
|
4
|
+
This package provides a unified tool system that works across all models
|
|
5
|
+
and providers, whether they have native tool APIs or require prompting.
|
|
6
|
+
|
|
7
|
+
Key components:
|
|
8
|
+
- Core types (ToolDefinition, ToolCall, ToolResult)
|
|
9
|
+
- Universal handler for all models
|
|
10
|
+
- Architecture-based parsing and formatting
|
|
11
|
+
- Tool registry for managing available tools
|
|
12
|
+
|
|
13
|
+
Example usage:
|
|
14
|
+
```python
|
|
15
|
+
from abstractcore.tools import ToolDefinition, UniversalToolHandler, register_tool
|
|
16
|
+
|
|
17
|
+
# Define a tool
|
|
18
|
+
def list_files(directory: str = ".", pattern: str = "*") -> str:
|
|
19
|
+
'''List files in a directory.'''
|
|
20
|
+
import os, fnmatch
|
|
21
|
+
files = [f for f in os.listdir(directory) if fnmatch.fnmatch(f, pattern)]
|
|
22
|
+
return "\n".join(files)
|
|
23
|
+
|
|
24
|
+
# Register the tool
|
|
25
|
+
tool_def = ToolDefinition.from_function(list_files)
|
|
26
|
+
|
|
27
|
+
# Create handler for a model
|
|
28
|
+
handler = UniversalToolHandler("qwen3-coder:30b")
|
|
29
|
+
|
|
30
|
+
# Get tool prompt for prompted models
|
|
31
|
+
if handler.supports_prompted:
|
|
32
|
+
tool_prompt = handler.format_tools_prompt([tool_def])
|
|
33
|
+
print("Add this to your system prompt:")
|
|
34
|
+
print(tool_prompt)
|
|
35
|
+
|
|
36
|
+
# Parse response for tool calls
|
|
37
|
+
response = "I'll list the files. <|tool_call|>{'name': 'list_files', 'arguments': {'directory': '.'}}"
|
|
38
|
+
tool_calls = handler.parse_response(response, mode="prompted")
|
|
39
|
+
|
|
40
|
+
if tool_calls.has_tool_calls():
|
|
41
|
+
print("Tool calls found:", tool_calls.tool_calls)
|
|
42
|
+
```
|
|
43
|
+
"""
|
|
44
|
+
|
|
45
|
+
# Core types
|
|
46
|
+
from .core import (
|
|
47
|
+
ToolDefinition,
|
|
48
|
+
ToolCall,
|
|
49
|
+
ToolResult,
|
|
50
|
+
ToolCallResponse,
|
|
51
|
+
tool
|
|
52
|
+
)
|
|
53
|
+
|
|
54
|
+
# Handler
|
|
55
|
+
from .handler import (
|
|
56
|
+
UniversalToolHandler,
|
|
57
|
+
create_handler
|
|
58
|
+
)
|
|
59
|
+
|
|
60
|
+
# Parser functions
|
|
61
|
+
from .parser import (
|
|
62
|
+
detect_tool_calls,
|
|
63
|
+
parse_tool_calls,
|
|
64
|
+
format_tool_prompt
|
|
65
|
+
)
|
|
66
|
+
|
|
67
|
+
# Registry
|
|
68
|
+
from .registry import (
|
|
69
|
+
ToolRegistry,
|
|
70
|
+
register_tool,
|
|
71
|
+
get_registry,
|
|
72
|
+
execute_tool,
|
|
73
|
+
execute_tools,
|
|
74
|
+
clear_registry
|
|
75
|
+
)
|
|
76
|
+
|
|
77
|
+
__all__ = [
|
|
78
|
+
# Core types
|
|
79
|
+
"ToolDefinition",
|
|
80
|
+
"ToolCall",
|
|
81
|
+
"ToolResult",
|
|
82
|
+
"ToolCallResponse",
|
|
83
|
+
"tool",
|
|
84
|
+
|
|
85
|
+
# Handler
|
|
86
|
+
"UniversalToolHandler",
|
|
87
|
+
"create_handler",
|
|
88
|
+
|
|
89
|
+
# Parser
|
|
90
|
+
"detect_tool_calls",
|
|
91
|
+
"parse_tool_calls",
|
|
92
|
+
"format_tool_prompt",
|
|
93
|
+
|
|
94
|
+
# Registry
|
|
95
|
+
"ToolRegistry",
|
|
96
|
+
"register_tool",
|
|
97
|
+
"get_registry",
|
|
98
|
+
"execute_tool",
|
|
99
|
+
"execute_tools",
|
|
100
|
+
"clear_registry",
|
|
101
|
+
]
|