signalwire-agents 0.1.13__py3-none-any.whl → 0.1.14__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.
@@ -18,7 +18,7 @@ A package for building AI agents using SignalWire's AI and SWML capabilities.
18
18
  from .core.logging_config import configure_logging
19
19
  configure_logging()
20
20
 
21
- __version__ = "0.1.13"
21
+ __version__ = "0.1.14"
22
22
 
23
23
  # Import core classes for easier access
24
24
  from .core.agent_base import AgentBase
@@ -31,19 +31,36 @@ from signalwire_agents.core.swml_builder import SWMLBuilder
31
31
  from signalwire_agents.core.function_result import SwaigFunctionResult
32
32
  from signalwire_agents.core.swaig_function import SWAIGFunction
33
33
 
34
- # Import skills to trigger discovery
35
- import signalwire_agents.skills
34
+ # Lazy import skills to avoid slow startup for CLI tools
35
+ # Skills are now loaded on-demand when requested
36
+ def _get_skill_registry():
37
+ """Lazy import and return skill registry"""
38
+ import signalwire_agents.skills
39
+ return signalwire_agents.skills.skill_registry
36
40
 
37
- # Import convenience functions from the CLI (if available)
38
- try:
39
- from signalwire_agents.cli.helpers import start_agent, run_agent, list_skills
40
- except ImportError:
41
- # CLI helpers not available, define minimal versions
42
- def start_agent(*args, **kwargs):
41
+ # Lazy import convenience functions from the CLI (if available)
42
+ def start_agent(*args, **kwargs):
43
+ """Start an agent (lazy import)"""
44
+ try:
45
+ from signalwire_agents.cli.helpers import start_agent as _start_agent
46
+ return _start_agent(*args, **kwargs)
47
+ except ImportError:
43
48
  raise NotImplementedError("CLI helpers not available")
44
- def run_agent(*args, **kwargs):
49
+
50
+ def run_agent(*args, **kwargs):
51
+ """Run an agent (lazy import)"""
52
+ try:
53
+ from signalwire_agents.cli.helpers import run_agent as _run_agent
54
+ return _run_agent(*args, **kwargs)
55
+ except ImportError:
45
56
  raise NotImplementedError("CLI helpers not available")
46
- def list_skills(*args, **kwargs):
57
+
58
+ def list_skills(*args, **kwargs):
59
+ """List available skills (lazy import)"""
60
+ try:
61
+ from signalwire_agents.cli.helpers import list_skills as _list_skills
62
+ return _list_skills(*args, **kwargs)
63
+ except ImportError:
47
64
  raise NotImplementedError("CLI helpers not available")
48
65
 
49
66
  __all__ = [
@@ -10,7 +10,6 @@ See LICENSE file in the project root for full license information.
10
10
  import argparse
11
11
  import sys
12
12
  from pathlib import Path
13
- from ..search.index_builder import IndexBuilder
14
13
 
15
14
  def main():
16
15
  """Main entry point for the build-search command"""
@@ -19,7 +18,7 @@ def main():
19
18
  formatter_class=argparse.RawDescriptionHelpFormatter,
20
19
  epilog="""
21
20
  Examples:
22
- # Basic usage with directory (defaults to sentence chunking with 50 sentences per chunk)
21
+ # Basic usage with directory (defaults to sentence chunking with 5 sentences per chunk)
23
22
  sw-search ./docs
24
23
 
25
24
  # Multiple directories
@@ -34,7 +33,7 @@ Examples:
34
33
  # Sentence-based chunking with custom parameters
35
34
  sw-search ./docs \\
36
35
  --chunking-strategy sentence \\
37
- --max-sentences-per-chunk 30 \\
36
+ --max-sentences-per-chunk 10 \\
38
37
  --split-newlines 2
39
38
 
40
39
  # Sliding window chunking
@@ -53,11 +52,25 @@ Examples:
53
52
  --chunking-strategy page \\
54
53
  --file-types pdf
55
54
 
55
+ # Semantic chunking (groups semantically similar sentences)
56
+ sw-search ./docs \\
57
+ --chunking-strategy semantic \\
58
+ --semantic-threshold 0.6
59
+
60
+ # Topic-based chunking (groups by topic changes)
61
+ sw-search ./docs \\
62
+ --chunking-strategy topic \\
63
+ --topic-threshold 0.2
64
+
65
+ # QA-optimized chunking (optimized for question-answering)
66
+ sw-search ./docs \\
67
+ --chunking-strategy qa
68
+
56
69
  # Full configuration example
57
70
  sw-search ./docs ./examples README.md \\
58
71
  --output ./knowledge.swsearch \\
59
72
  --chunking-strategy sentence \\
60
- --max-sentences-per-chunk 50 \\
73
+ --max-sentences-per-chunk 8 \\
61
74
  --file-types md,txt,rst,py \\
62
75
  --exclude "**/test/**,**/__pycache__/**" \\
63
76
  --languages en,es,fr \\
@@ -88,7 +101,7 @@ Examples:
88
101
 
89
102
  parser.add_argument(
90
103
  '--chunking-strategy',
91
- choices=['sentence', 'sliding', 'paragraph', 'page'],
104
+ choices=['sentence', 'sliding', 'paragraph', 'page', 'semantic', 'topic', 'qa'],
92
105
  default='sentence',
93
106
  help='Chunking strategy to use (default: sentence)'
94
107
  )
@@ -96,8 +109,8 @@ Examples:
96
109
  parser.add_argument(
97
110
  '--max-sentences-per-chunk',
98
111
  type=int,
99
- default=50,
100
- help='Maximum sentences per chunk for sentence strategy (default: 50)'
112
+ default=5,
113
+ help='Maximum sentences per chunk for sentence strategy (default: 5)'
101
114
  )
102
115
 
103
116
  parser.add_argument(
@@ -117,7 +130,7 @@ Examples:
117
130
  parser.add_argument(
118
131
  '--split-newlines',
119
132
  type=int,
120
- help='Split on multiple newlines for sentence strategy (optional)'
133
+ help='Split on multiple newlines (for sentence strategy)'
121
134
  )
122
135
 
123
136
  parser.add_argument(
@@ -148,6 +161,13 @@ Examples:
148
161
  help='Comma-separated tags to add to all chunks'
149
162
  )
150
163
 
164
+ parser.add_argument(
165
+ '--index-nlp-backend',
166
+ choices=['nltk', 'spacy'],
167
+ default='nltk',
168
+ help='NLP backend for document processing: nltk (fast, default) or spacy (better quality, slower)'
169
+ )
170
+
151
171
  parser.add_argument(
152
172
  '--verbose',
153
173
  action='store_true',
@@ -160,6 +180,20 @@ Examples:
160
180
  help='Validate the created index after building'
161
181
  )
162
182
 
183
+ parser.add_argument(
184
+ '--semantic-threshold',
185
+ type=float,
186
+ default=0.5,
187
+ help='Similarity threshold for semantic chunking (default: 0.5)'
188
+ )
189
+
190
+ parser.add_argument(
191
+ '--topic-threshold',
192
+ type=float,
193
+ default=0.3,
194
+ help='Similarity threshold for topic chunking (default: 0.3)'
195
+ )
196
+
163
197
  args = parser.parse_args()
164
198
 
165
199
  # Validate sources
@@ -204,6 +238,7 @@ Examples:
204
238
  print(f" Languages: {languages}")
205
239
  print(f" Model: {args.model}")
206
240
  print(f" Chunking strategy: {args.chunking_strategy}")
241
+ print(f" Index NLP backend: {args.index_nlp_backend}")
207
242
 
208
243
  if args.chunking_strategy == 'sentence':
209
244
  print(f" Max sentences per chunk: {args.max_sentences_per_chunk}")
@@ -216,12 +251,19 @@ Examples:
216
251
  print(f" Chunking by paragraphs (double newlines)")
217
252
  elif args.chunking_strategy == 'page':
218
253
  print(f" Chunking by pages")
254
+ elif args.chunking_strategy == 'semantic':
255
+ print(f" Semantic chunking (similarity threshold: {args.semantic_threshold})")
256
+ elif args.chunking_strategy == 'topic':
257
+ print(f" Topic-based chunking (similarity threshold: {args.topic_threshold})")
258
+ elif args.chunking_strategy == 'qa':
259
+ print(f" QA-optimized chunking")
219
260
 
220
261
  print(f" Tags: {tags}")
221
262
  print()
222
263
 
223
264
  try:
224
- # Create index builder
265
+ # Create index builder - import only when actually needed
266
+ from ..search.index_builder import IndexBuilder
225
267
  builder = IndexBuilder(
226
268
  model_name=args.model,
227
269
  chunking_strategy=args.chunking_strategy,
@@ -229,7 +271,10 @@ Examples:
229
271
  chunk_size=args.chunk_size,
230
272
  chunk_overlap=args.overlap_size,
231
273
  split_newlines=args.split_newlines,
232
- verbose=args.verbose
274
+ index_nlp_backend=args.index_nlp_backend,
275
+ verbose=args.verbose,
276
+ semantic_threshold=args.semantic_threshold,
277
+ topic_threshold=args.topic_threshold
233
278
  )
234
279
 
235
280
  # Build index with multiple sources
@@ -316,8 +361,8 @@ def search_command():
316
361
  parser.add_argument('--count', type=int, default=5, help='Number of results to return (default: 5)')
317
362
  parser.add_argument('--distance-threshold', type=float, default=0.0, help='Minimum similarity score (default: 0.0)')
318
363
  parser.add_argument('--tags', help='Comma-separated tags to filter by')
319
- parser.add_argument('--nlp-backend', choices=['nltk', 'spacy'], default='nltk',
320
- help='NLP backend to use: nltk (fast, default) or spacy (better quality, requires model download)')
364
+ parser.add_argument('--query-nlp-backend', choices=['nltk', 'spacy'], default='nltk',
365
+ help='NLP backend for query processing: nltk (fast, default) or spacy (better quality, slower)')
321
366
  parser.add_argument('--verbose', action='store_true', help='Show detailed information')
322
367
  parser.add_argument('--json', action='store_true', help='Output results as JSON')
323
368
  parser.add_argument('--no-content', action='store_true', help='Hide content in results (show only metadata)')
@@ -349,11 +394,11 @@ def search_command():
349
394
  if args.verbose:
350
395
  print(f"Index contains {stats['total_chunks']} chunks from {stats['total_files']} files")
351
396
  print(f"Searching for: '{args.query}'")
352
- print(f"NLP Backend: {args.nlp_backend}")
397
+ print(f"Query NLP Backend: {args.query_nlp_backend}")
353
398
  print()
354
399
 
355
400
  # Preprocess query
356
- enhanced = preprocess_query(args.query, vector=True, nlp_backend=args.nlp_backend)
401
+ enhanced = preprocess_query(args.query, vector=True, query_nlp_backend=args.query_nlp_backend)
357
402
 
358
403
  # Parse tags if provided
359
404
  tags = [tag.strip() for tag in args.tags.split(',')] if args.tags else None
@@ -437,6 +482,121 @@ def console_entry_point():
437
482
  """Console script entry point for pip installation"""
438
483
  import sys
439
484
 
485
+ # Fast help check - show help without importing heavy modules
486
+ if len(sys.argv) > 1 and sys.argv[1] in ['--help', '-h']:
487
+ print("""usage: sw-search [-h] [--output OUTPUT] [--chunking-strategy {sentence,sliding,paragraph,page,semantic,topic,qa}]
488
+ [--max-sentences-per-chunk MAX_SENTENCES_PER_CHUNK] [--chunk-size CHUNK_SIZE]
489
+ [--overlap-size OVERLAP_SIZE] [--split-newlines SPLIT_NEWLINES] [--file-types FILE_TYPES]
490
+ [--exclude EXCLUDE] [--languages LANGUAGES] [--model MODEL] [--tags TAGS]
491
+ [--index-nlp-backend {nltk,spacy}] [--verbose] [--validate]
492
+ [--semantic-threshold SEMANTIC_THRESHOLD] [--topic-threshold TOPIC_THRESHOLD]
493
+ sources [sources ...]
494
+
495
+ Build local search index from documents
496
+
497
+ positional arguments:
498
+ sources Source files and/or directories to index
499
+
500
+ options:
501
+ -h, --help show this help message and exit
502
+ --output OUTPUT Output .swsearch file (default: sources.swsearch)
503
+ --chunking-strategy {sentence,sliding,paragraph,page,semantic,topic,qa}
504
+ Chunking strategy to use (default: sentence)
505
+ --max-sentences-per-chunk MAX_SENTENCES_PER_CHUNK
506
+ Maximum sentences per chunk for sentence strategy (default: 5)
507
+ --chunk-size CHUNK_SIZE
508
+ Chunk size in words for sliding window strategy (default: 50)
509
+ --overlap-size OVERLAP_SIZE
510
+ Overlap size in words for sliding window strategy (default: 10)
511
+ --split-newlines SPLIT_NEWLINES
512
+ Split on multiple newlines (for sentence strategy)
513
+ --file-types FILE_TYPES
514
+ Comma-separated file extensions to include for directories (default: md,txt,rst)
515
+ --exclude EXCLUDE Comma-separated glob patterns to exclude (e.g., "**/test/**,**/__pycache__/**")
516
+ --languages LANGUAGES
517
+ Comma-separated language codes (default: en)
518
+ --model MODEL Sentence transformer model name (default: sentence-transformers/all-mpnet-base-v2)
519
+ --tags TAGS Comma-separated tags to add to all chunks
520
+ --index-nlp-backend {nltk,spacy}
521
+ NLP backend for document processing: nltk (fast, default) or spacy (better quality, slower)
522
+ --verbose Enable verbose output
523
+ --validate Validate the created index after building
524
+ --semantic-threshold SEMANTIC_THRESHOLD
525
+ Similarity threshold for semantic chunking (default: 0.5)
526
+ --topic-threshold TOPIC_THRESHOLD
527
+ Similarity threshold for topic chunking (default: 0.3)
528
+
529
+ Examples:
530
+ # Basic usage with directory (defaults to sentence chunking with 5 sentences per chunk)
531
+ sw-search ./docs
532
+
533
+ # Multiple directories
534
+ sw-search ./docs ./examples --file-types md,txt,py
535
+
536
+ # Individual files
537
+ sw-search README.md ./docs/guide.md ./src/main.py
538
+
539
+ # Mixed sources (directories and files)
540
+ sw-search ./docs README.md ./examples specific_file.txt --file-types md,txt,py
541
+
542
+ # Sentence-based chunking with custom parameters
543
+ sw-search ./docs \\
544
+ --chunking-strategy sentence \\
545
+ --max-sentences-per-chunk 10 \\
546
+ --split-newlines 2
547
+
548
+ # Sliding window chunking
549
+ sw-search ./docs \\
550
+ --chunking-strategy sliding \\
551
+ --chunk-size 100 \\
552
+ --overlap-size 20
553
+
554
+ # Paragraph-based chunking
555
+ sw-search ./docs \\
556
+ --chunking-strategy paragraph \\
557
+ --file-types md,txt,rst
558
+
559
+ # Page-based chunking (good for PDFs)
560
+ sw-search ./docs \\
561
+ --chunking-strategy page \\
562
+ --file-types pdf
563
+
564
+ # Semantic chunking (groups semantically similar sentences)
565
+ sw-search ./docs \\
566
+ --chunking-strategy semantic \\
567
+ --semantic-threshold 0.6
568
+
569
+ # Topic-based chunking (groups by topic changes)
570
+ sw-search ./docs \\
571
+ --chunking-strategy topic \\
572
+ --topic-threshold 0.2
573
+
574
+ # QA-optimized chunking (optimized for question-answering)
575
+ sw-search ./docs \\
576
+ --chunking-strategy qa
577
+
578
+ # Full configuration example
579
+ sw-search ./docs ./examples README.md \\
580
+ --output ./knowledge.swsearch \\
581
+ --chunking-strategy sentence \\
582
+ --max-sentences-per-chunk 8 \\
583
+ --file-types md,txt,rst,py \\
584
+ --exclude "**/test/**,**/__pycache__/**" \\
585
+ --languages en,es,fr \\
586
+ --model sentence-transformers/all-mpnet-base-v2 \\
587
+ --tags documentation,api \\
588
+ --verbose
589
+
590
+ # Validate an existing index
591
+ sw-search validate ./docs.swsearch
592
+
593
+ # Search within an index
594
+ sw-search search ./docs.swsearch "how to create an agent"
595
+ sw-search search ./docs.swsearch "API reference" --count 3 --verbose
596
+ sw-search search ./docs.swsearch "configuration" --tags documentation --json
597
+ """)
598
+ return
599
+
440
600
  # Check for subcommands
441
601
  if len(sys.argv) > 1:
442
602
  if sys.argv[1] == 'validate':