abstractcore 2.3.7__py3-none-any.whl → 2.3.9__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-2.3.7.dist-info → abstractcore-2.3.9.dist-info}/METADATA +1 -1
- {abstractcore-2.3.7.dist-info → abstractcore-2.3.9.dist-info}/RECORD +18 -18
- abstractllm/apps/extractor.py +19 -11
- abstractllm/apps/judge.py +2 -6
- abstractllm/apps/summarizer.py +14 -5
- abstractllm/processing/basic_extractor.py +4 -2
- abstractllm/processing/basic_judge.py +9 -5
- abstractllm/processing/basic_summarizer.py +5 -3
- abstractllm/providers/base.py +3 -2
- abstractllm/providers/huggingface_provider.py +37 -0
- abstractllm/providers/lmstudio_provider.py +8 -6
- abstractllm/providers/mlx_provider.py +37 -0
- abstractllm/providers/mock_provider.py +32 -0
- abstractllm/utils/version.py +9 -39
- {abstractcore-2.3.7.dist-info → abstractcore-2.3.9.dist-info}/WHEEL +0 -0
- {abstractcore-2.3.7.dist-info → abstractcore-2.3.9.dist-info}/entry_points.txt +0 -0
- {abstractcore-2.3.7.dist-info → abstractcore-2.3.9.dist-info}/licenses/LICENSE +0 -0
- {abstractcore-2.3.7.dist-info → abstractcore-2.3.9.dist-info}/top_level.txt +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: abstractcore
|
|
3
|
-
Version: 2.3.
|
|
3
|
+
Version: 2.3.9
|
|
4
4
|
Summary: Unified interface to all LLM providers with essential infrastructure for tool calling, streaming, and model management
|
|
5
5
|
Author: Laurent-Philippe Albou
|
|
6
6
|
Maintainer: Laurent-Philippe Albou
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
abstractcore-2.3.
|
|
1
|
+
abstractcore-2.3.9.dist-info/licenses/LICENSE,sha256=PI2v_4HMvd6050uDD_4AY_8PzBnu2asa3RKbdDjowTA,1078
|
|
2
2
|
abstractllm/__init__.py,sha256=UWHXV-OyMpDeBsCFfLTTgVqkFTrj-uQWVqgFtkfjtxU,1859
|
|
3
3
|
abstractllm/apps/__init__.py,sha256=H6fOR28gyBW8bDCEAft2RUZhNmRYA_7fF91szKBjhpA,30
|
|
4
4
|
abstractllm/apps/__main__.py,sha256=YyAHo-0O4yAJ5JeinsioIM6Ytam2i4eq6UQt2oWB2s0,1579
|
|
5
|
-
abstractllm/apps/extractor.py,sha256=
|
|
6
|
-
abstractllm/apps/judge.py,sha256=
|
|
7
|
-
abstractllm/apps/summarizer.py,sha256=
|
|
5
|
+
abstractllm/apps/extractor.py,sha256=iBDBStD17K1YV22jMlAa2gAk8oywn96r6QW2DEMjZEs,23733
|
|
6
|
+
abstractllm/apps/judge.py,sha256=W6ILCLfDbMbuKsiaf0VOK86TEvi46z3yyViukG7kZWA,23151
|
|
7
|
+
abstractllm/apps/summarizer.py,sha256=YBTV98-YenxVYzZLVFB9YkGaCy57sHaEyzMFGPDvDyo,14128
|
|
8
8
|
abstractllm/architectures/__init__.py,sha256=-4JucAM7JkMWShWKkePoclxrUHRKgaG36UTguJihE0U,1046
|
|
9
9
|
abstractllm/architectures/detection.py,sha256=PYYzJ73tXI5ssJOpEL6-mHBmTreYXIq5f4nsfqtrpmw,9465
|
|
10
10
|
abstractllm/architectures/enums.py,sha256=9vIv2vDBEKhxwzwH9iaSAyf-iVj3p8y9loMeN_mYTJ8,3821
|
|
@@ -23,16 +23,16 @@ abstractllm/embeddings/manager.py,sha256=YCW1r7ldd_mZshRjWNiNLIyhZktFl1SIiwgDDf4
|
|
|
23
23
|
abstractllm/embeddings/models.py,sha256=bsPAzL6gv57AVii8O15PT0kxfwRkOml3f3njJN4UDi4,4874
|
|
24
24
|
abstractllm/events/__init__.py,sha256=Z7WIDjerS3G6zjcjiRH3tHIbKdFNzlWnibHMNxkWWzo,11064
|
|
25
25
|
abstractllm/processing/__init__.py,sha256=t6hiakQjcZROT4pw9ZFt2q6fF3vf5VpdMKG2EWlsFd8,540
|
|
26
|
-
abstractllm/processing/basic_extractor.py,sha256=
|
|
27
|
-
abstractllm/processing/basic_judge.py,sha256=
|
|
28
|
-
abstractllm/processing/basic_summarizer.py,sha256=
|
|
26
|
+
abstractllm/processing/basic_extractor.py,sha256=IvigIkwF41G8SvsjVMoniHAu39gLKmKIp5-nTAoXx4E,49827
|
|
27
|
+
abstractllm/processing/basic_judge.py,sha256=LQkloGBL96w65E-Qtp-Gf78_KuOrrA72otzk18h-_WA,32213
|
|
28
|
+
abstractllm/processing/basic_summarizer.py,sha256=c420K0ExF3rrf-l4EuIAh2YKLxdxOloJujtuGTlk7AE,25488
|
|
29
29
|
abstractllm/providers/__init__.py,sha256=UTpR2Bf_ICFG7M--1kxUmNXs4gl026Tp-KI9zJlvMKU,574
|
|
30
30
|
abstractllm/providers/anthropic_provider.py,sha256=BM8Vu89c974yicvFwlsJ5C3N0wR9Kkt1pOszViWCwAQ,19694
|
|
31
|
-
abstractllm/providers/base.py,sha256=
|
|
32
|
-
abstractllm/providers/huggingface_provider.py,sha256=
|
|
33
|
-
abstractllm/providers/lmstudio_provider.py,sha256=
|
|
34
|
-
abstractllm/providers/mlx_provider.py,sha256=
|
|
35
|
-
abstractllm/providers/mock_provider.py,sha256=
|
|
31
|
+
abstractllm/providers/base.py,sha256=Pp1CuJmhsH_4PZBrRKzmccvbhvgu6JS-hvDNJkpElfE,42820
|
|
32
|
+
abstractllm/providers/huggingface_provider.py,sha256=3RLqdZUbA9GgWRB0jpjtUMEs2FuzQwUlwC0mU-A1ysQ,42282
|
|
33
|
+
abstractllm/providers/lmstudio_provider.py,sha256=vhZJWDVu9hiC1wCoZoNODY14axXsy_dv52TQ13bsxmw,16004
|
|
34
|
+
abstractllm/providers/mlx_provider.py,sha256=eANGeexmJIS4KWn77fRBOJRkXvwgh7irAtu3kDVIVBA,15629
|
|
35
|
+
abstractllm/providers/mock_provider.py,sha256=tIjA57Hlwu3vNODOZShNn0tY9HWvz1p4z-HyD_bsvbo,5741
|
|
36
36
|
abstractllm/providers/ollama_provider.py,sha256=SkXD5gjuzeu9Thqnt4pRPSi-cjWxwuZGV2x5YMm26jo,19340
|
|
37
37
|
abstractllm/providers/openai_provider.py,sha256=xGFrSkbCrsBnWnho1U2aMCBdzfCqf121wU1EFGmU3YQ,21678
|
|
38
38
|
abstractllm/providers/streaming.py,sha256=KQUH1DB-7UvuZP0_Wrcajj1P-9jdqnQfpIEeSYkxVFU,31153
|
|
@@ -54,9 +54,9 @@ abstractllm/utils/cli.py,sha256=PcA5AKvAr3bADT9x9OytfE4MDUVh48q8DcbIu9CLkj8,5687
|
|
|
54
54
|
abstractllm/utils/self_fixes.py,sha256=QEDwNTW80iQM4ftfEY3Ghz69F018oKwLM9yeRCYZOvw,5886
|
|
55
55
|
abstractllm/utils/structured_logging.py,sha256=2_bbMRjOvf0gHsRejncel_-PrhYUsOUySX_eaPcQopc,15827
|
|
56
56
|
abstractllm/utils/token_utils.py,sha256=wAZpqiPh4eL8ppl1lNjqTzxCmlvdJ1Xu62UJyaDq09Y,21096
|
|
57
|
-
abstractllm/utils/version.py,sha256=
|
|
58
|
-
abstractcore-2.3.
|
|
59
|
-
abstractcore-2.3.
|
|
60
|
-
abstractcore-2.3.
|
|
61
|
-
abstractcore-2.3.
|
|
62
|
-
abstractcore-2.3.
|
|
57
|
+
abstractllm/utils/version.py,sha256=qbYRDP1iRl-eg3KmpLRoIZcJHiyGDC7qZgJJwcRgurQ,605
|
|
58
|
+
abstractcore-2.3.9.dist-info/METADATA,sha256=Hbqs0h67_AlDTRW676trCHF_I_6n0J8qjOauSIeM46U,19399
|
|
59
|
+
abstractcore-2.3.9.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
60
|
+
abstractcore-2.3.9.dist-info/entry_points.txt,sha256=plz04HNXbCbQkmEQj_8xKWW8x7zBxus68HD_04-IARM,306
|
|
61
|
+
abstractcore-2.3.9.dist-info/top_level.txt,sha256=Md-8odCjB7hTNnE5hucnifAoLrL9HvRPffZmCq2jpoI,12
|
|
62
|
+
abstractcore-2.3.9.dist-info/RECORD,,
|
abstractllm/apps/extractor.py
CHANGED
|
@@ -52,6 +52,18 @@ from ..processing import BasicExtractor
|
|
|
52
52
|
from ..core.factory import create_llm
|
|
53
53
|
|
|
54
54
|
|
|
55
|
+
def timeout_type(value):
|
|
56
|
+
"""Parse timeout value - accepts None, 'none', or float"""
|
|
57
|
+
if value is None:
|
|
58
|
+
return None
|
|
59
|
+
if isinstance(value, str) and value.lower() == 'none':
|
|
60
|
+
return None
|
|
61
|
+
try:
|
|
62
|
+
return float(value)
|
|
63
|
+
except ValueError:
|
|
64
|
+
raise argparse.ArgumentTypeError(f"Invalid timeout value: {value}. Use 'none' for unlimited or a number in seconds.")
|
|
65
|
+
|
|
66
|
+
|
|
55
67
|
def read_file_content(file_path: str) -> str:
|
|
56
68
|
"""
|
|
57
69
|
Read content from various file types
|
|
@@ -295,9 +307,9 @@ Default model setup:
|
|
|
295
307
|
|
|
296
308
|
parser.add_argument(
|
|
297
309
|
'--timeout',
|
|
298
|
-
type=
|
|
299
|
-
default=
|
|
300
|
-
help='HTTP request timeout in seconds for LLM providers (default:
|
|
310
|
+
type=timeout_type,
|
|
311
|
+
default=None,
|
|
312
|
+
help='HTTP request timeout in seconds for LLM providers (default: unlimited). Use "none" for unlimited timeout or specify seconds (e.g., 600 for 10 minutes)'
|
|
301
313
|
)
|
|
302
314
|
|
|
303
315
|
parser.add_argument(
|
|
@@ -342,13 +354,7 @@ Default model setup:
|
|
|
342
354
|
sys.exit(1)
|
|
343
355
|
|
|
344
356
|
# Validate timeout parameter
|
|
345
|
-
if args.timeout < 30.0:
|
|
346
|
-
print("Error: Timeout must be at least 30 seconds")
|
|
347
|
-
sys.exit(1)
|
|
348
357
|
|
|
349
|
-
if args.timeout > 7200.0: # 2 hours
|
|
350
|
-
print("Error: Timeout cannot exceed 7200 seconds (2 hours)")
|
|
351
|
-
sys.exit(1)
|
|
352
358
|
|
|
353
359
|
# Validate provider/model pair
|
|
354
360
|
if args.provider and not args.model:
|
|
@@ -423,7 +429,8 @@ Default model setup:
|
|
|
423
429
|
llm=llm,
|
|
424
430
|
max_chunk_size=adjusted_chunk_size,
|
|
425
431
|
max_tokens=args.max_tokens,
|
|
426
|
-
max_output_tokens=args.max_output_tokens
|
|
432
|
+
max_output_tokens=args.max_output_tokens,
|
|
433
|
+
timeout=args.timeout
|
|
427
434
|
)
|
|
428
435
|
else:
|
|
429
436
|
# Default configuration
|
|
@@ -434,7 +441,8 @@ Default model setup:
|
|
|
434
441
|
extractor = BasicExtractor(
|
|
435
442
|
max_chunk_size=args.chunk_size,
|
|
436
443
|
max_tokens=args.max_tokens,
|
|
437
|
-
max_output_tokens=args.max_output_tokens
|
|
444
|
+
max_output_tokens=args.max_output_tokens,
|
|
445
|
+
timeout=args.timeout
|
|
438
446
|
)
|
|
439
447
|
except RuntimeError as e:
|
|
440
448
|
# Handle default model not available
|
abstractllm/apps/judge.py
CHANGED
|
@@ -383,9 +383,8 @@ Default model setup:
|
|
|
383
383
|
|
|
384
384
|
parser.add_argument(
|
|
385
385
|
'--timeout',
|
|
386
|
-
|
|
387
|
-
default=
|
|
388
|
-
help='HTTP request timeout in seconds for LLM providers (default: 300)'
|
|
386
|
+
default=None,
|
|
387
|
+
help='HTTP request timeout in seconds for LLM providers (default: None = infininity)'
|
|
389
388
|
)
|
|
390
389
|
|
|
391
390
|
# Parse arguments
|
|
@@ -398,9 +397,6 @@ Default model setup:
|
|
|
398
397
|
sys.exit(1)
|
|
399
398
|
|
|
400
399
|
# Validate timeout
|
|
401
|
-
if args.timeout < 30.0:
|
|
402
|
-
print("Error: Timeout must be at least 30 seconds")
|
|
403
|
-
sys.exit(1)
|
|
404
400
|
|
|
405
401
|
# Validate provider/model pair
|
|
406
402
|
if args.provider and not args.model:
|
abstractllm/apps/summarizer.py
CHANGED
|
@@ -240,6 +240,12 @@ Default model setup:
|
|
|
240
240
|
help='Show detailed progress information'
|
|
241
241
|
)
|
|
242
242
|
|
|
243
|
+
parser.add_argument(
|
|
244
|
+
'--timeout',
|
|
245
|
+
default=None,
|
|
246
|
+
help='HTTP request timeout in seconds for LLM providers (default: None = unlimited)'
|
|
247
|
+
)
|
|
248
|
+
|
|
243
249
|
# Parse arguments
|
|
244
250
|
args = parser.parse_args()
|
|
245
251
|
|
|
@@ -286,12 +292,13 @@ Default model setup:
|
|
|
286
292
|
if args.verbose:
|
|
287
293
|
print(f"Initializing summarizer ({args.provider}, {args.model}, {args.max_tokens} token context, {args.max_output_tokens} output tokens)...")
|
|
288
294
|
|
|
289
|
-
llm = create_llm(args.provider, model=args.model, max_tokens=args.max_tokens, max_output_tokens=args.max_output_tokens)
|
|
295
|
+
llm = create_llm(args.provider, model=args.model, max_tokens=args.max_tokens, max_output_tokens=args.max_output_tokens, timeout=args.timeout)
|
|
290
296
|
summarizer = BasicSummarizer(
|
|
291
297
|
llm,
|
|
292
298
|
max_chunk_size=args.chunk_size,
|
|
293
299
|
max_tokens=args.max_tokens,
|
|
294
|
-
max_output_tokens=args.max_output_tokens
|
|
300
|
+
max_output_tokens=args.max_output_tokens,
|
|
301
|
+
timeout=args.timeout
|
|
295
302
|
)
|
|
296
303
|
else:
|
|
297
304
|
# Default configuration with chunk size override
|
|
@@ -302,12 +309,13 @@ Default model setup:
|
|
|
302
309
|
print(f"Initializing summarizer (ollama, gemma3:1b-it-qat, {args.max_tokens} token context, {args.max_output_tokens} output tokens, {args.chunk_size} chunk size)...")
|
|
303
310
|
|
|
304
311
|
try:
|
|
305
|
-
llm = create_llm("ollama", model="gemma3:1b-it-qat", max_tokens=args.max_tokens, max_output_tokens=args.max_output_tokens)
|
|
312
|
+
llm = create_llm("ollama", model="gemma3:1b-it-qat", max_tokens=args.max_tokens, max_output_tokens=args.max_output_tokens, timeout=args.timeout)
|
|
306
313
|
summarizer = BasicSummarizer(
|
|
307
314
|
llm,
|
|
308
315
|
max_chunk_size=args.chunk_size,
|
|
309
316
|
max_tokens=args.max_tokens,
|
|
310
|
-
max_output_tokens=args.max_output_tokens
|
|
317
|
+
max_output_tokens=args.max_output_tokens,
|
|
318
|
+
timeout=args.timeout
|
|
311
319
|
)
|
|
312
320
|
except Exception as e:
|
|
313
321
|
# Handle default model not available
|
|
@@ -327,7 +335,8 @@ Default model setup:
|
|
|
327
335
|
summarizer = BasicSummarizer(
|
|
328
336
|
max_chunk_size=args.chunk_size,
|
|
329
337
|
max_tokens=args.max_tokens,
|
|
330
|
-
max_output_tokens=args.max_output_tokens
|
|
338
|
+
max_output_tokens=args.max_output_tokens,
|
|
339
|
+
timeout=args.timeout
|
|
331
340
|
)
|
|
332
341
|
except RuntimeError as e:
|
|
333
342
|
# Handle default model not available
|
|
@@ -53,7 +53,8 @@ class BasicExtractor:
|
|
|
53
53
|
llm: Optional[AbstractLLMInterface] = None,
|
|
54
54
|
max_chunk_size: int = 8000,
|
|
55
55
|
max_tokens: int = 32000,
|
|
56
|
-
max_output_tokens: int = 8000
|
|
56
|
+
max_output_tokens: int = 8000,
|
|
57
|
+
timeout: Optional[float] = None
|
|
57
58
|
):
|
|
58
59
|
"""Initialize the extractor
|
|
59
60
|
|
|
@@ -62,10 +63,11 @@ class BasicExtractor:
|
|
|
62
63
|
max_chunk_size: Maximum characters per chunk for long documents (default 8000)
|
|
63
64
|
max_tokens: Maximum total tokens for LLM context (default 32000)
|
|
64
65
|
max_output_tokens: Maximum tokens for LLM output generation (default 8000)
|
|
66
|
+
timeout: HTTP request timeout in seconds. None for unlimited timeout (default None)
|
|
65
67
|
"""
|
|
66
68
|
if llm is None:
|
|
67
69
|
try:
|
|
68
|
-
self.llm = create_llm("ollama", model="qwen3:4b-instruct-2507-q4_K_M", max_tokens=max_tokens, max_output_tokens=max_output_tokens)
|
|
70
|
+
self.llm = create_llm("ollama", model="qwen3:4b-instruct-2507-q4_K_M", max_tokens=max_tokens, max_output_tokens=max_output_tokens, timeout=timeout)
|
|
69
71
|
except Exception as e:
|
|
70
72
|
error_msg = (
|
|
71
73
|
f"❌ Failed to initialize default Ollama model 'qwen3:4b-instruct-2507-q4_K_M': {e}\n\n"
|
|
@@ -118,7 +118,8 @@ class BasicJudge:
|
|
|
118
118
|
temperature: float = 0.1, # Low temperature for consistent evaluation
|
|
119
119
|
max_tokens: int = 32000,
|
|
120
120
|
max_output_tokens: int = 8000,
|
|
121
|
-
debug: bool = False
|
|
121
|
+
debug: bool = False,
|
|
122
|
+
timeout: Optional[float] = None
|
|
122
123
|
):
|
|
123
124
|
"""Initialize the judge
|
|
124
125
|
|
|
@@ -128,12 +129,13 @@ class BasicJudge:
|
|
|
128
129
|
max_tokens: Maximum total tokens for LLM context (default 32000)
|
|
129
130
|
max_output_tokens: Maximum tokens for LLM output generation (default 8000)
|
|
130
131
|
debug: Enable debug output showing raw LLM responses (default False)
|
|
132
|
+
timeout: HTTP request timeout in seconds. None for unlimited timeout (default None)
|
|
131
133
|
"""
|
|
132
134
|
if llm is None:
|
|
133
135
|
try:
|
|
134
136
|
# Use low temperature for consistent evaluation
|
|
135
137
|
self.llm = create_llm("ollama", model="qwen3:4b-instruct-2507-q4_K_M",
|
|
136
|
-
max_tokens=max_tokens, max_output_tokens=max_output_tokens, temperature=temperature)
|
|
138
|
+
max_tokens=max_tokens, max_output_tokens=max_output_tokens, temperature=temperature, timeout=timeout)
|
|
137
139
|
except Exception as e:
|
|
138
140
|
error_msg = (
|
|
139
141
|
f"❌ Failed to initialize default Ollama model 'qwen3:4b-instruct-2507-q4_K_M': {e}\n\n"
|
|
@@ -663,6 +665,7 @@ def create_judge(
|
|
|
663
665
|
max_tokens: int = 32000,
|
|
664
666
|
max_output_tokens: int = 8000,
|
|
665
667
|
debug: bool = False,
|
|
668
|
+
timeout: Optional[float] = None,
|
|
666
669
|
**kwargs
|
|
667
670
|
) -> BasicJudge:
|
|
668
671
|
"""
|
|
@@ -675,13 +678,14 @@ def create_judge(
|
|
|
675
678
|
max_tokens: Maximum total tokens for LLM context (default 32000)
|
|
676
679
|
max_output_tokens: Maximum tokens for LLM output generation (default 8000)
|
|
677
680
|
debug: Enable debug output showing raw LLM responses (default False)
|
|
681
|
+
timeout: HTTP request timeout in seconds. None for unlimited timeout (default None)
|
|
678
682
|
**kwargs: Additional arguments passed to create_llm
|
|
679
683
|
|
|
680
684
|
Returns:
|
|
681
685
|
BasicJudge instance
|
|
682
686
|
"""
|
|
683
687
|
if provider and model:
|
|
684
|
-
llm = create_llm(provider, model=model, temperature=temperature, max_tokens=max_tokens, max_output_tokens=max_output_tokens, **kwargs)
|
|
685
|
-
return BasicJudge(llm=llm, temperature=temperature, max_tokens=max_tokens, max_output_tokens=max_output_tokens, debug=debug)
|
|
688
|
+
llm = create_llm(provider, model=model, temperature=temperature, max_tokens=max_tokens, max_output_tokens=max_output_tokens, timeout=timeout, **kwargs)
|
|
689
|
+
return BasicJudge(llm=llm, temperature=temperature, max_tokens=max_tokens, max_output_tokens=max_output_tokens, debug=debug, timeout=timeout)
|
|
686
690
|
else:
|
|
687
|
-
return BasicJudge(temperature=temperature, max_tokens=max_tokens, max_output_tokens=max_output_tokens, debug=debug)
|
|
691
|
+
return BasicJudge(temperature=temperature, max_tokens=max_tokens, max_output_tokens=max_output_tokens, debug=debug, timeout=timeout)
|
|
@@ -82,7 +82,8 @@ class BasicSummarizer:
|
|
|
82
82
|
llm: Optional[AbstractLLMInterface] = None,
|
|
83
83
|
max_chunk_size: int = 8000,
|
|
84
84
|
max_tokens: int = 32000,
|
|
85
|
-
max_output_tokens: int = 8000
|
|
85
|
+
max_output_tokens: int = 8000,
|
|
86
|
+
timeout: Optional[float] = None
|
|
86
87
|
):
|
|
87
88
|
"""
|
|
88
89
|
Initialize the summarizer
|
|
@@ -91,12 +92,13 @@ class BasicSummarizer:
|
|
|
91
92
|
llm: AbstractLLM instance (any provider). If None, attempts to create ollama gemma3:1b-it-qat
|
|
92
93
|
max_chunk_size: Maximum characters per chunk for long documents (default 8000)
|
|
93
94
|
max_tokens: Maximum total tokens for LLM context (default 32000)
|
|
94
|
-
max_output_tokens: Maximum tokens for LLM output generation (default
|
|
95
|
+
max_output_tokens: Maximum tokens for LLM output generation (default 8000)
|
|
96
|
+
timeout: HTTP request timeout in seconds. None for unlimited timeout (default None)
|
|
95
97
|
"""
|
|
96
98
|
if llm is None:
|
|
97
99
|
try:
|
|
98
100
|
# Default to gemma3:1b-it-qat with configurable token limits
|
|
99
|
-
self.llm = create_llm("ollama", model="gemma3:1b-it-qat", max_tokens=max_tokens, max_output_tokens=max_output_tokens)
|
|
101
|
+
self.llm = create_llm("ollama", model="gemma3:1b-it-qat", max_tokens=max_tokens, max_output_tokens=max_output_tokens, timeout=timeout)
|
|
100
102
|
except Exception as e:
|
|
101
103
|
error_msg = (
|
|
102
104
|
f"❌ Failed to initialize default Ollama model 'gemma3:1b-it-qat': {e}\n\n"
|
abstractllm/providers/base.py
CHANGED
|
@@ -48,8 +48,9 @@ class BaseProvider(AbstractLLMInterface, ABC):
|
|
|
48
48
|
self.model_capabilities = get_model_capabilities(model)
|
|
49
49
|
|
|
50
50
|
# Setup timeout configuration
|
|
51
|
-
|
|
52
|
-
self.
|
|
51
|
+
# Default to None for unlimited timeout
|
|
52
|
+
self._timeout = kwargs.get('timeout', None) # Default None for unlimited HTTP requests
|
|
53
|
+
self._tool_timeout = kwargs.get('tool_timeout', None) # Default None for unlimited tool execution
|
|
53
54
|
|
|
54
55
|
# Setup tool execution mode
|
|
55
56
|
# execute_tools: True = AbstractCore executes tools (legacy mode)
|
|
@@ -62,6 +62,9 @@ class HuggingFaceProvider(BaseProvider):
|
|
|
62
62
|
|
|
63
63
|
super().__init__(model, **kwargs)
|
|
64
64
|
|
|
65
|
+
# Handle timeout parameter for local models
|
|
66
|
+
self._handle_timeout_parameter(kwargs)
|
|
67
|
+
|
|
65
68
|
# Initialize tool handler
|
|
66
69
|
self.tool_handler = UniversalToolHandler(model)
|
|
67
70
|
|
|
@@ -427,6 +430,40 @@ class HuggingFaceProvider(BaseProvider):
|
|
|
427
430
|
|
|
428
431
|
return sorted(similar_models)
|
|
429
432
|
|
|
433
|
+
def _handle_timeout_parameter(self, kwargs: Dict[str, Any]) -> None:
|
|
434
|
+
"""
|
|
435
|
+
Handle timeout parameter for HuggingFace provider.
|
|
436
|
+
|
|
437
|
+
Since HuggingFace models run locally (both transformers and GGUF),
|
|
438
|
+
timeout parameters don't apply. If a non-None timeout is provided,
|
|
439
|
+
issue a warning and treat it as None (infinity).
|
|
440
|
+
|
|
441
|
+
Args:
|
|
442
|
+
kwargs: Initialization kwargs that may contain timeout
|
|
443
|
+
"""
|
|
444
|
+
timeout_value = kwargs.get('timeout')
|
|
445
|
+
if timeout_value is not None:
|
|
446
|
+
import warnings
|
|
447
|
+
warnings.warn(
|
|
448
|
+
f"HuggingFace provider runs models locally and does not support timeout parameters. "
|
|
449
|
+
f"Provided timeout={timeout_value} will be ignored and treated as None (unlimited).",
|
|
450
|
+
UserWarning,
|
|
451
|
+
stacklevel=3
|
|
452
|
+
)
|
|
453
|
+
# Force timeout to None for local models
|
|
454
|
+
self._timeout = None
|
|
455
|
+
else:
|
|
456
|
+
# Keep None value (unlimited timeout is appropriate for local models)
|
|
457
|
+
self._timeout = None
|
|
458
|
+
|
|
459
|
+
def _update_http_client_timeout(self) -> None:
|
|
460
|
+
"""
|
|
461
|
+
HuggingFace provider doesn't use HTTP clients for model inference.
|
|
462
|
+
Local models (transformers and GGUF) don't have timeout constraints.
|
|
463
|
+
"""
|
|
464
|
+
# No-op for local models - they don't use HTTP clients
|
|
465
|
+
pass
|
|
466
|
+
|
|
430
467
|
def generate(self, *args, **kwargs):
|
|
431
468
|
"""Public generate method that includes telemetry"""
|
|
432
469
|
return self.generate_with_telemetry(*args, **kwargs)
|
|
@@ -30,10 +30,11 @@ class LMStudioProvider(BaseProvider):
|
|
|
30
30
|
|
|
31
31
|
self.base_url = base_url.rstrip('/')
|
|
32
32
|
|
|
33
|
-
#
|
|
33
|
+
# Get timeout value - None means unlimited timeout
|
|
34
34
|
timeout_value = getattr(self, '_timeout', None)
|
|
35
|
-
if
|
|
36
|
-
|
|
35
|
+
# Validate timeout if provided (None is allowed for unlimited)
|
|
36
|
+
if timeout_value is not None and timeout_value <= 0:
|
|
37
|
+
timeout_value = None # Invalid timeout becomes unlimited
|
|
37
38
|
|
|
38
39
|
try:
|
|
39
40
|
self.client = httpx.Client(timeout=timeout_value)
|
|
@@ -295,10 +296,11 @@ class LMStudioProvider(BaseProvider):
|
|
|
295
296
|
# Create new client with updated timeout
|
|
296
297
|
self.client.close()
|
|
297
298
|
|
|
298
|
-
#
|
|
299
|
+
# Get timeout value - None means unlimited timeout
|
|
299
300
|
timeout_value = getattr(self, '_timeout', None)
|
|
300
|
-
if
|
|
301
|
-
|
|
301
|
+
# Validate timeout if provided (None is allowed for unlimited)
|
|
302
|
+
if timeout_value is not None and timeout_value <= 0:
|
|
303
|
+
timeout_value = None # Invalid timeout becomes unlimited
|
|
302
304
|
|
|
303
305
|
self.client = httpx.Client(timeout=timeout_value)
|
|
304
306
|
except Exception as e:
|
|
@@ -24,6 +24,9 @@ class MLXProvider(BaseProvider):
|
|
|
24
24
|
def __init__(self, model: str = "mlx-community/Mistral-7B-Instruct-v0.1-4bit", **kwargs):
|
|
25
25
|
super().__init__(model, **kwargs)
|
|
26
26
|
|
|
27
|
+
# Handle timeout parameter for local models
|
|
28
|
+
self._handle_timeout_parameter(kwargs)
|
|
29
|
+
|
|
27
30
|
# Initialize tool handler
|
|
28
31
|
self.tool_handler = UniversalToolHandler(model)
|
|
29
32
|
|
|
@@ -93,6 +96,40 @@ class MLXProvider(BaseProvider):
|
|
|
93
96
|
if hasattr(self, 'logger'):
|
|
94
97
|
self.logger.warning(f"Error during unload: {e}")
|
|
95
98
|
|
|
99
|
+
def _handle_timeout_parameter(self, kwargs: Dict[str, Any]) -> None:
|
|
100
|
+
"""
|
|
101
|
+
Handle timeout parameter for MLX provider.
|
|
102
|
+
|
|
103
|
+
Since MLX models run locally on Apple Silicon,
|
|
104
|
+
timeout parameters don't apply. If a non-None timeout is provided,
|
|
105
|
+
issue a warning and treat it as None (infinity).
|
|
106
|
+
|
|
107
|
+
Args:
|
|
108
|
+
kwargs: Initialization kwargs that may contain timeout
|
|
109
|
+
"""
|
|
110
|
+
timeout_value = kwargs.get('timeout')
|
|
111
|
+
if timeout_value is not None:
|
|
112
|
+
import warnings
|
|
113
|
+
warnings.warn(
|
|
114
|
+
f"MLX provider runs models locally on Apple Silicon and does not support timeout parameters. "
|
|
115
|
+
f"Provided timeout={timeout_value} will be ignored and treated as None (unlimited).",
|
|
116
|
+
UserWarning,
|
|
117
|
+
stacklevel=3
|
|
118
|
+
)
|
|
119
|
+
# Force timeout to None for local models
|
|
120
|
+
self._timeout = None
|
|
121
|
+
else:
|
|
122
|
+
# Keep None value (unlimited timeout is appropriate for local models)
|
|
123
|
+
self._timeout = None
|
|
124
|
+
|
|
125
|
+
def _update_http_client_timeout(self) -> None:
|
|
126
|
+
"""
|
|
127
|
+
MLX provider doesn't use HTTP clients for model inference.
|
|
128
|
+
Local models on Apple Silicon don't have timeout constraints.
|
|
129
|
+
"""
|
|
130
|
+
# No-op for local models - they don't use HTTP clients
|
|
131
|
+
pass
|
|
132
|
+
|
|
96
133
|
def generate(self, *args, **kwargs):
|
|
97
134
|
"""Public generate method that includes telemetry"""
|
|
98
135
|
return self.generate_with_telemetry(*args, **kwargs)
|
|
@@ -20,6 +20,10 @@ class MockProvider(BaseProvider):
|
|
|
20
20
|
|
|
21
21
|
def __init__(self, model: str = "mock-model", **kwargs):
|
|
22
22
|
super().__init__(model, **kwargs)
|
|
23
|
+
|
|
24
|
+
# Handle timeout parameter for mock provider
|
|
25
|
+
self._handle_timeout_parameter(kwargs)
|
|
26
|
+
|
|
23
27
|
# Mock provider uses prompted strategy for structured output
|
|
24
28
|
self.model_capabilities = {"structured_output": "prompted"}
|
|
25
29
|
|
|
@@ -106,6 +110,34 @@ class MockProvider(BaseProvider):
|
|
|
106
110
|
|
|
107
111
|
return json.dumps(mock_data)
|
|
108
112
|
|
|
113
|
+
def _handle_timeout_parameter(self, kwargs: Dict[str, Any]) -> None:
|
|
114
|
+
"""
|
|
115
|
+
Handle timeout parameter for Mock provider.
|
|
116
|
+
|
|
117
|
+
Mock provider simulates responses instantly, so timeout parameters
|
|
118
|
+
don't apply. If a non-None timeout is provided, it's accepted but
|
|
119
|
+
has no effect on mock generation.
|
|
120
|
+
|
|
121
|
+
Args:
|
|
122
|
+
kwargs: Initialization kwargs that may contain timeout
|
|
123
|
+
"""
|
|
124
|
+
timeout_value = kwargs.get('timeout')
|
|
125
|
+
if timeout_value is not None:
|
|
126
|
+
# For mock provider, we accept timeout but it has no effect
|
|
127
|
+
# No warning needed since this is for testing
|
|
128
|
+
self._timeout = timeout_value
|
|
129
|
+
else:
|
|
130
|
+
# Keep None value
|
|
131
|
+
self._timeout = None
|
|
132
|
+
|
|
133
|
+
def _update_http_client_timeout(self) -> None:
|
|
134
|
+
"""
|
|
135
|
+
Mock provider doesn't use HTTP clients.
|
|
136
|
+
Timeout changes have no effect on mock responses.
|
|
137
|
+
"""
|
|
138
|
+
# No-op for mock provider - no HTTP clients used
|
|
139
|
+
pass
|
|
140
|
+
|
|
109
141
|
def get_capabilities(self) -> List[str]:
|
|
110
142
|
"""Get mock capabilities"""
|
|
111
143
|
return ["tools", "streaming", "vision"]
|
abstractllm/utils/version.py
CHANGED
|
@@ -1,44 +1,14 @@
|
|
|
1
1
|
"""
|
|
2
2
|
Version management for AbstractCore.
|
|
3
3
|
|
|
4
|
-
This module provides a
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
import os
|
|
9
|
-
import tomllib
|
|
10
|
-
from pathlib import Path
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
def get_version() -> str:
|
|
14
|
-
"""
|
|
15
|
-
Get the package version from pyproject.toml.
|
|
16
|
-
|
|
17
|
-
Returns:
|
|
18
|
-
str: The package version
|
|
19
|
-
|
|
20
|
-
Raises:
|
|
21
|
-
FileNotFoundError: If pyproject.toml is not found
|
|
22
|
-
KeyError: If version is not found in pyproject.toml
|
|
23
|
-
"""
|
|
24
|
-
# Get the project root directory (where pyproject.toml is located)
|
|
25
|
-
# When imported as a module, we need to go up from abstractllm/utils/ to the project root
|
|
26
|
-
current_dir = Path(__file__).parent # abstractllm/utils/
|
|
27
|
-
project_root = current_dir.parent.parent # Go up two levels: utils -> abstractllm -> project_root
|
|
28
|
-
pyproject_path = project_root / "pyproject.toml"
|
|
29
|
-
|
|
30
|
-
if not pyproject_path.exists():
|
|
31
|
-
raise FileNotFoundError(f"pyproject.toml not found at {pyproject_path}")
|
|
32
|
-
|
|
33
|
-
# Read and parse pyproject.toml
|
|
34
|
-
with open(pyproject_path, "rb") as f:
|
|
35
|
-
data = tomllib.load(f)
|
|
36
|
-
|
|
37
|
-
try:
|
|
38
|
-
return data["project"]["version"]
|
|
39
|
-
except KeyError:
|
|
40
|
-
raise KeyError("Version not found in pyproject.toml [project] section")
|
|
4
|
+
This module provides the package version as a static constant that serves as the
|
|
5
|
+
single source of truth for the Python code. The version is also maintained in
|
|
6
|
+
pyproject.toml for packaging, requiring manual synchronization during releases.
|
|
41
7
|
|
|
8
|
+
This approach ensures reliable version access in all deployment scenarios,
|
|
9
|
+
including when the package is installed from PyPI where pyproject.toml is not available.
|
|
10
|
+
"""
|
|
42
11
|
|
|
43
|
-
#
|
|
44
|
-
|
|
12
|
+
# Package version - update this when releasing new versions
|
|
13
|
+
# This must be manually synchronized with the version in pyproject.toml
|
|
14
|
+
__version__ = "2.3.9"
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|