npcpy 1.2.35__tar.gz → 1.2.37__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.
Files changed (77) hide show
  1. {npcpy-1.2.35/npcpy.egg-info → npcpy-1.2.37}/PKG-INFO +173 -1
  2. {npcpy-1.2.35 → npcpy-1.2.37}/README.md +172 -0
  3. npcpy-1.2.37/npcpy/__init__.py +14 -0
  4. {npcpy-1.2.35 → npcpy-1.2.37}/npcpy/gen/image_gen.py +5 -2
  5. {npcpy-1.2.35 → npcpy-1.2.37}/npcpy/gen/response.py +262 -64
  6. {npcpy-1.2.35 → npcpy-1.2.37}/npcpy/llm_funcs.py +478 -832
  7. npcpy-1.2.37/npcpy/ml_funcs.py +746 -0
  8. npcpy-1.2.37/npcpy/npc_array.py +1294 -0
  9. {npcpy-1.2.35 → npcpy-1.2.37}/npcpy/npc_compiler.py +348 -252
  10. {npcpy-1.2.35 → npcpy-1.2.37}/npcpy/npc_sysenv.py +17 -2
  11. {npcpy-1.2.35 → npcpy-1.2.37}/npcpy/serve.py +684 -90
  12. {npcpy-1.2.35 → npcpy-1.2.37}/npcpy/sql/npcsql.py +96 -59
  13. {npcpy-1.2.35 → npcpy-1.2.37/npcpy.egg-info}/PKG-INFO +173 -1
  14. {npcpy-1.2.35 → npcpy-1.2.37}/npcpy.egg-info/SOURCES.txt +3 -0
  15. {npcpy-1.2.35 → npcpy-1.2.37}/setup.py +1 -1
  16. npcpy-1.2.37/tests/test_npc_array.py +539 -0
  17. {npcpy-1.2.35 → npcpy-1.2.37}/tests/test_npc_compiler.py +28 -19
  18. npcpy-1.2.35/npcpy/__init__.py +0 -6
  19. {npcpy-1.2.35 → npcpy-1.2.37}/LICENSE +0 -0
  20. {npcpy-1.2.35 → npcpy-1.2.37}/MANIFEST.in +0 -0
  21. {npcpy-1.2.35 → npcpy-1.2.37}/npcpy/data/__init__.py +0 -0
  22. {npcpy-1.2.35 → npcpy-1.2.37}/npcpy/data/audio.py +0 -0
  23. {npcpy-1.2.35 → npcpy-1.2.37}/npcpy/data/data_models.py +0 -0
  24. {npcpy-1.2.35 → npcpy-1.2.37}/npcpy/data/image.py +0 -0
  25. {npcpy-1.2.35 → npcpy-1.2.37}/npcpy/data/load.py +0 -0
  26. {npcpy-1.2.35 → npcpy-1.2.37}/npcpy/data/text.py +0 -0
  27. {npcpy-1.2.35 → npcpy-1.2.37}/npcpy/data/video.py +0 -0
  28. {npcpy-1.2.35 → npcpy-1.2.37}/npcpy/data/web.py +0 -0
  29. {npcpy-1.2.35 → npcpy-1.2.37}/npcpy/ft/__init__.py +0 -0
  30. {npcpy-1.2.35 → npcpy-1.2.37}/npcpy/ft/diff.py +0 -0
  31. {npcpy-1.2.35 → npcpy-1.2.37}/npcpy/ft/ge.py +0 -0
  32. {npcpy-1.2.35 → npcpy-1.2.37}/npcpy/ft/memory_trainer.py +0 -0
  33. {npcpy-1.2.35 → npcpy-1.2.37}/npcpy/ft/model_ensembler.py +0 -0
  34. {npcpy-1.2.35 → npcpy-1.2.37}/npcpy/ft/rl.py +0 -0
  35. {npcpy-1.2.35 → npcpy-1.2.37}/npcpy/ft/sft.py +0 -0
  36. {npcpy-1.2.35 → npcpy-1.2.37}/npcpy/ft/usft.py +0 -0
  37. {npcpy-1.2.35 → npcpy-1.2.37}/npcpy/gen/__init__.py +0 -0
  38. {npcpy-1.2.35 → npcpy-1.2.37}/npcpy/gen/audio_gen.py +0 -0
  39. {npcpy-1.2.35 → npcpy-1.2.37}/npcpy/gen/embeddings.py +0 -0
  40. {npcpy-1.2.35 → npcpy-1.2.37}/npcpy/gen/ocr.py +0 -0
  41. {npcpy-1.2.35 → npcpy-1.2.37}/npcpy/gen/video_gen.py +0 -0
  42. {npcpy-1.2.35 → npcpy-1.2.37}/npcpy/main.py +0 -0
  43. {npcpy-1.2.35 → npcpy-1.2.37}/npcpy/memory/__init__.py +0 -0
  44. {npcpy-1.2.35 → npcpy-1.2.37}/npcpy/memory/command_history.py +0 -0
  45. {npcpy-1.2.35 → npcpy-1.2.37}/npcpy/memory/kg_vis.py +0 -0
  46. {npcpy-1.2.35 → npcpy-1.2.37}/npcpy/memory/knowledge_graph.py +0 -0
  47. {npcpy-1.2.35 → npcpy-1.2.37}/npcpy/memory/memory_processor.py +0 -0
  48. {npcpy-1.2.35 → npcpy-1.2.37}/npcpy/memory/search.py +0 -0
  49. {npcpy-1.2.35 → npcpy-1.2.37}/npcpy/mix/__init__.py +0 -0
  50. {npcpy-1.2.35 → npcpy-1.2.37}/npcpy/mix/debate.py +0 -0
  51. {npcpy-1.2.35 → npcpy-1.2.37}/npcpy/npcs.py +0 -0
  52. {npcpy-1.2.35 → npcpy-1.2.37}/npcpy/sql/__init__.py +0 -0
  53. {npcpy-1.2.35 → npcpy-1.2.37}/npcpy/sql/ai_function_tools.py +0 -0
  54. {npcpy-1.2.35 → npcpy-1.2.37}/npcpy/sql/database_ai_adapters.py +0 -0
  55. {npcpy-1.2.35 → npcpy-1.2.37}/npcpy/sql/database_ai_functions.py +0 -0
  56. {npcpy-1.2.35 → npcpy-1.2.37}/npcpy/sql/model_runner.py +0 -0
  57. {npcpy-1.2.35 → npcpy-1.2.37}/npcpy/sql/sql_model_compiler.py +0 -0
  58. {npcpy-1.2.35 → npcpy-1.2.37}/npcpy/tools.py +0 -0
  59. {npcpy-1.2.35 → npcpy-1.2.37}/npcpy/work/__init__.py +0 -0
  60. {npcpy-1.2.35 → npcpy-1.2.37}/npcpy/work/desktop.py +0 -0
  61. {npcpy-1.2.35 → npcpy-1.2.37}/npcpy/work/plan.py +0 -0
  62. {npcpy-1.2.35 → npcpy-1.2.37}/npcpy/work/trigger.py +0 -0
  63. {npcpy-1.2.35 → npcpy-1.2.37}/npcpy.egg-info/dependency_links.txt +0 -0
  64. {npcpy-1.2.35 → npcpy-1.2.37}/npcpy.egg-info/requires.txt +0 -0
  65. {npcpy-1.2.35 → npcpy-1.2.37}/npcpy.egg-info/top_level.txt +0 -0
  66. {npcpy-1.2.35 → npcpy-1.2.37}/setup.cfg +0 -0
  67. {npcpy-1.2.35 → npcpy-1.2.37}/tests/test_audio.py +0 -0
  68. {npcpy-1.2.35 → npcpy-1.2.37}/tests/test_command_history.py +0 -0
  69. {npcpy-1.2.35 → npcpy-1.2.37}/tests/test_image.py +0 -0
  70. {npcpy-1.2.35 → npcpy-1.2.37}/tests/test_llm_funcs.py +0 -0
  71. {npcpy-1.2.35 → npcpy-1.2.37}/tests/test_load.py +0 -0
  72. {npcpy-1.2.35 → npcpy-1.2.37}/tests/test_npcsql.py +0 -0
  73. {npcpy-1.2.35 → npcpy-1.2.37}/tests/test_response.py +0 -0
  74. {npcpy-1.2.35 → npcpy-1.2.37}/tests/test_serve.py +0 -0
  75. {npcpy-1.2.35 → npcpy-1.2.37}/tests/test_text.py +0 -0
  76. {npcpy-1.2.35 → npcpy-1.2.37}/tests/test_tools.py +0 -0
  77. {npcpy-1.2.35 → npcpy-1.2.37}/tests/test_web.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: npcpy
3
- Version: 1.2.35
3
+ Version: 1.2.37
4
4
  Summary: npcpy is the premier open-source library for integrating LLMs and Agents into python systems.
5
5
  Home-page: https://github.com/NPC-Worldwide/npcpy
6
6
  Author: Christopher Agostino
@@ -607,6 +607,178 @@ else:
607
607
  The intention for this model ensembler system is to mimic human cognition: pattern-matched gut reactions (System 1 of Kahneman) for familiar queries, falling back to deliberate reasoning (System 2 of Kahneman) for novel problems. Genetic algorithms evolve both knowledge structures and model specializations over time.
608
608
 
609
609
 
610
+ ## NPCArray - NumPy for AI
611
+
612
+ `npcpy` provides `NPCArray`, a NumPy-like interface for working with populations of models (LLMs, sklearn, PyTorch) at scale. Think of it as vectorized operations over AI models.
613
+
614
+ ### Core Concepts
615
+ - Model arrays support vectorized operations
616
+ - Operations are lazy until `.collect()` is called (like Spark)
617
+ - Same interface works for single models (treated as length-1 arrays)
618
+ - Supports ensemble voting, consensus, evolution, and more
619
+
620
+ ### Basic Usage
621
+
622
+ ```python
623
+ from npcpy.npc_array import NPCArray
624
+
625
+ # Create array of LLMs
626
+ models = NPCArray.from_llms(
627
+ ['llama3.2', 'gemma3:1b'],
628
+ providers='ollama'
629
+ )
630
+
631
+ print(f"Model array shape: {models.shape}") # (2,)
632
+
633
+ # Inference across all models - returns shape (n_models, n_prompts)
634
+ result = models.infer("What is 2+2? Just the number.").collect()
635
+
636
+ print(f"Model 1: {result.data[0, 0]}")
637
+ print(f"Model 2: {result.data[1, 0]}")
638
+ ```
639
+
640
+ ### Lazy Chaining & Ensemble Operations
641
+
642
+ ```python
643
+ from npcpy.npc_array import NPCArray
644
+
645
+ models = NPCArray.from_llms(['llama3.2', 'gemma3:1b', 'mistral:7b'])
646
+
647
+ # Build lazy computation graph - nothing executed yet
648
+ result = (
649
+ models
650
+ .infer("Is Python compiled or interpreted? One word.")
651
+ .map(lambda r: r.strip().lower()) # Clean responses
652
+ .vote(axis=0) # Majority voting across models
653
+ )
654
+
655
+ # Show the computation plan
656
+ result.explain()
657
+
658
+ # Now execute
659
+ answer = result.collect()
660
+ print(f"Consensus: {answer.data[0]}")
661
+ ```
662
+
663
+ ### Parameter Sweeps with Meshgrid
664
+
665
+ ```python
666
+ from npcpy.npc_array import NPCArray
667
+
668
+ # Cartesian product over parameters
669
+ configs = NPCArray.meshgrid(
670
+ models=['llama3.2', 'gemma3:1b'],
671
+ temperatures=[0.0, 0.5, 1.0]
672
+ )
673
+
674
+ print(f"Config array shape: {configs.shape}") # (6,) = 2 models × 3 temps
675
+
676
+ # Run inference with each config
677
+ result = configs.infer("Complete: The quick brown fox").collect()
678
+ ```
679
+
680
+ ### Matrix Sampling with get_llm_response
681
+
682
+ The `get_llm_response` function supports `matrix` and `n_samples` parameters for exploration:
683
+
684
+ ```python
685
+ from npcpy.llm_funcs import get_llm_response
686
+
687
+ # Matrix parameter - cartesian product over specified params
688
+ result = get_llm_response(
689
+ "Write a creative opening line.",
690
+ matrix={
691
+ 'model': ['llama3.2', 'gemma3:1b'],
692
+ 'temperature': [0.5, 1.0]
693
+ }
694
+ )
695
+ print(f"Number of runs: {len(result['runs'])}") # 4 = 2×2
696
+
697
+ # n_samples - multiple samples from same config
698
+ result = get_llm_response(
699
+ "Pick a random number 1-100.",
700
+ model='llama3.2',
701
+ n_samples=5
702
+ )
703
+ print(f"Samples: {[r['response'] for r in result['runs']]}")
704
+
705
+ # Combine both for full exploration
706
+ result = get_llm_response(
707
+ "Flip a coin: heads or tails?",
708
+ matrix={'model': ['llama3.2', 'gemma3:1b']},
709
+ n_samples=3 # 2 models × 3 samples = 6 runs
710
+ )
711
+ ```
712
+
713
+ ### sklearn Integration
714
+
715
+ ```python
716
+ from npcpy.npc_array import NPCArray
717
+ from sklearn.ensemble import RandomForestClassifier
718
+ from sklearn.linear_model import LogisticRegression
719
+ import numpy as np
720
+
721
+ # Create sample data
722
+ X_train = np.random.randn(100, 4)
723
+ y_train = (X_train[:, 0] > 0).astype(int)
724
+
725
+ # Pre-fit models
726
+ rf = RandomForestClassifier(n_estimators=10).fit(X_train, y_train)
727
+ lr = LogisticRegression().fit(X_train, y_train)
728
+
729
+ # Create array from fitted models
730
+ models = NPCArray.from_sklearn([rf, lr])
731
+
732
+ # Vectorized prediction
733
+ X_test = np.random.randn(20, 4)
734
+ predictions = models.predict(X_test).collect()
735
+
736
+ print(f"RF predictions: {predictions.data[0]}")
737
+ print(f"LR predictions: {predictions.data[1]}")
738
+ ```
739
+
740
+ ### ML Functions with Grid Search
741
+
742
+ ```python
743
+ from npcpy.ml_funcs import fit_model, score_model, ensemble_predict
744
+
745
+ # Grid search via matrix parameter
746
+ result = fit_model(
747
+ X_train, y_train,
748
+ model='RandomForestClassifier',
749
+ matrix={
750
+ 'n_estimators': [10, 50, 100],
751
+ 'max_depth': [3, 5, 10]
752
+ }
753
+ )
754
+
755
+ print(f"Fitted {len(result['models'])} model configurations")
756
+
757
+ # Ensemble voting with multiple models
758
+ predictions = ensemble_predict(X_test, result['models'], method='vote')
759
+ ```
760
+
761
+ ### Quick Utilities
762
+
763
+ ```python
764
+ from npcpy.npc_array import infer_matrix, ensemble_vote
765
+
766
+ # Quick matrix inference
767
+ result = infer_matrix(
768
+ prompts=["Hello", "Goodbye"],
769
+ models=['llama3.2', 'gemma3:1b']
770
+ )
771
+
772
+ # Quick ensemble vote
773
+ answer = ensemble_vote(
774
+ "What is the capital of France? One word.",
775
+ models=['llama3.2', 'gemma3:1b']
776
+ )
777
+ print(f"Voted answer: {answer}")
778
+ ```
779
+
780
+ See `examples/npc_array_examples.py` for more comprehensive examples.
781
+
610
782
 
611
783
  ## Serving an NPC Team
612
784
 
@@ -511,6 +511,178 @@ else:
511
511
  The intention for this model ensembler system is to mimic human cognition: pattern-matched gut reactions (System 1 of Kahneman) for familiar queries, falling back to deliberate reasoning (System 2 of Kahneman) for novel problems. Genetic algorithms evolve both knowledge structures and model specializations over time.
512
512
 
513
513
 
514
+ ## NPCArray - NumPy for AI
515
+
516
+ `npcpy` provides `NPCArray`, a NumPy-like interface for working with populations of models (LLMs, sklearn, PyTorch) at scale. Think of it as vectorized operations over AI models.
517
+
518
+ ### Core Concepts
519
+ - Model arrays support vectorized operations
520
+ - Operations are lazy until `.collect()` is called (like Spark)
521
+ - Same interface works for single models (treated as length-1 arrays)
522
+ - Supports ensemble voting, consensus, evolution, and more
523
+
524
+ ### Basic Usage
525
+
526
+ ```python
527
+ from npcpy.npc_array import NPCArray
528
+
529
+ # Create array of LLMs
530
+ models = NPCArray.from_llms(
531
+ ['llama3.2', 'gemma3:1b'],
532
+ providers='ollama'
533
+ )
534
+
535
+ print(f"Model array shape: {models.shape}") # (2,)
536
+
537
+ # Inference across all models - returns shape (n_models, n_prompts)
538
+ result = models.infer("What is 2+2? Just the number.").collect()
539
+
540
+ print(f"Model 1: {result.data[0, 0]}")
541
+ print(f"Model 2: {result.data[1, 0]}")
542
+ ```
543
+
544
+ ### Lazy Chaining & Ensemble Operations
545
+
546
+ ```python
547
+ from npcpy.npc_array import NPCArray
548
+
549
+ models = NPCArray.from_llms(['llama3.2', 'gemma3:1b', 'mistral:7b'])
550
+
551
+ # Build lazy computation graph - nothing executed yet
552
+ result = (
553
+ models
554
+ .infer("Is Python compiled or interpreted? One word.")
555
+ .map(lambda r: r.strip().lower()) # Clean responses
556
+ .vote(axis=0) # Majority voting across models
557
+ )
558
+
559
+ # Show the computation plan
560
+ result.explain()
561
+
562
+ # Now execute
563
+ answer = result.collect()
564
+ print(f"Consensus: {answer.data[0]}")
565
+ ```
566
+
567
+ ### Parameter Sweeps with Meshgrid
568
+
569
+ ```python
570
+ from npcpy.npc_array import NPCArray
571
+
572
+ # Cartesian product over parameters
573
+ configs = NPCArray.meshgrid(
574
+ models=['llama3.2', 'gemma3:1b'],
575
+ temperatures=[0.0, 0.5, 1.0]
576
+ )
577
+
578
+ print(f"Config array shape: {configs.shape}") # (6,) = 2 models × 3 temps
579
+
580
+ # Run inference with each config
581
+ result = configs.infer("Complete: The quick brown fox").collect()
582
+ ```
583
+
584
+ ### Matrix Sampling with get_llm_response
585
+
586
+ The `get_llm_response` function supports `matrix` and `n_samples` parameters for exploration:
587
+
588
+ ```python
589
+ from npcpy.llm_funcs import get_llm_response
590
+
591
+ # Matrix parameter - cartesian product over specified params
592
+ result = get_llm_response(
593
+ "Write a creative opening line.",
594
+ matrix={
595
+ 'model': ['llama3.2', 'gemma3:1b'],
596
+ 'temperature': [0.5, 1.0]
597
+ }
598
+ )
599
+ print(f"Number of runs: {len(result['runs'])}") # 4 = 2×2
600
+
601
+ # n_samples - multiple samples from same config
602
+ result = get_llm_response(
603
+ "Pick a random number 1-100.",
604
+ model='llama3.2',
605
+ n_samples=5
606
+ )
607
+ print(f"Samples: {[r['response'] for r in result['runs']]}")
608
+
609
+ # Combine both for full exploration
610
+ result = get_llm_response(
611
+ "Flip a coin: heads or tails?",
612
+ matrix={'model': ['llama3.2', 'gemma3:1b']},
613
+ n_samples=3 # 2 models × 3 samples = 6 runs
614
+ )
615
+ ```
616
+
617
+ ### sklearn Integration
618
+
619
+ ```python
620
+ from npcpy.npc_array import NPCArray
621
+ from sklearn.ensemble import RandomForestClassifier
622
+ from sklearn.linear_model import LogisticRegression
623
+ import numpy as np
624
+
625
+ # Create sample data
626
+ X_train = np.random.randn(100, 4)
627
+ y_train = (X_train[:, 0] > 0).astype(int)
628
+
629
+ # Pre-fit models
630
+ rf = RandomForestClassifier(n_estimators=10).fit(X_train, y_train)
631
+ lr = LogisticRegression().fit(X_train, y_train)
632
+
633
+ # Create array from fitted models
634
+ models = NPCArray.from_sklearn([rf, lr])
635
+
636
+ # Vectorized prediction
637
+ X_test = np.random.randn(20, 4)
638
+ predictions = models.predict(X_test).collect()
639
+
640
+ print(f"RF predictions: {predictions.data[0]}")
641
+ print(f"LR predictions: {predictions.data[1]}")
642
+ ```
643
+
644
+ ### ML Functions with Grid Search
645
+
646
+ ```python
647
+ from npcpy.ml_funcs import fit_model, score_model, ensemble_predict
648
+
649
+ # Grid search via matrix parameter
650
+ result = fit_model(
651
+ X_train, y_train,
652
+ model='RandomForestClassifier',
653
+ matrix={
654
+ 'n_estimators': [10, 50, 100],
655
+ 'max_depth': [3, 5, 10]
656
+ }
657
+ )
658
+
659
+ print(f"Fitted {len(result['models'])} model configurations")
660
+
661
+ # Ensemble voting with multiple models
662
+ predictions = ensemble_predict(X_test, result['models'], method='vote')
663
+ ```
664
+
665
+ ### Quick Utilities
666
+
667
+ ```python
668
+ from npcpy.npc_array import infer_matrix, ensemble_vote
669
+
670
+ # Quick matrix inference
671
+ result = infer_matrix(
672
+ prompts=["Hello", "Goodbye"],
673
+ models=['llama3.2', 'gemma3:1b']
674
+ )
675
+
676
+ # Quick ensemble vote
677
+ answer = ensemble_vote(
678
+ "What is the capital of France? One word.",
679
+ models=['llama3.2', 'gemma3:1b']
680
+ )
681
+ print(f"Voted answer: {answer}")
682
+ ```
683
+
684
+ See `examples/npc_array_examples.py` for more comprehensive examples.
685
+
514
686
 
515
687
  ## Serving an NPC Team
516
688
 
@@ -0,0 +1,14 @@
1
+ from . import npc_compiler
2
+ from . import npc_sysenv
3
+ from . import llm_funcs
4
+ from . import ml_funcs
5
+ from . import npc_array
6
+ from . import sql
7
+ from . import work
8
+ from . import gen
9
+
10
+ # Expose key classes at package level
11
+ from .npc_array import NPCArray, ResponseTensor, LazyResult, infer_matrix, ensemble_vote
12
+ from .npc_compiler import NPC, Team, Jinx
13
+ from .llm_funcs import get_llm_response, check_llm_command, execute_llm_command
14
+ from .ml_funcs import fit_model, predict_model, score_model, ensemble_predict
@@ -363,7 +363,8 @@ def generate_image(
363
363
  api_url: Optional[str] = None,
364
364
  attachments: Union[List[Union[str, bytes, Image.Image]], None] = None,
365
365
  save_path: Optional[str] = None,
366
- custom_model_path: Optional[str] = None, # <--- NEW: Accept custom_model_path
366
+ custom_model_path: Optional[str] = None, # <--- NEW: Accept custom_model_path,
367
+
367
368
  ):
368
369
  """
369
370
  Unified function to generate or edit images using various providers.
@@ -429,7 +430,9 @@ def generate_image(
429
430
  attachments=attachments,
430
431
  height=height,
431
432
  width=width,
432
- n_images=n_images
433
+ n_images=n_images,
434
+ api_key=api_key
435
+
433
436
  )
434
437
  all_generated_pil_images.extend(images)
435
438