npcpy 1.2.36__py3-none-any.whl → 1.3.1__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.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: npcpy
3
- Version: 1.2.36
3
+ Version: 1.3.1
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
@@ -275,9 +275,8 @@ output = context['research_summary']
275
275
  "code": '''
276
276
  # Access outputs from previous steps.
277
277
  research_summary = context['initial_llm_research']
278
- # The output of a declarative jinx call (like 'file_reader') is stored under its step name.
279
- # The actual content we want is the 'output' of the *last step* within that sub-jinx.
280
- file_summary = context['read_and_process_source_file'].get('output', 'No file summary available.')
278
+ # The file_reader jinx returns its output directly; also keep a fallback of file_raw_content.
279
+ file_summary = context.get('read_and_process_source_file', '') or context.get('file_raw_content', 'No file summary available.')
281
280
 
282
281
  prompt = f"""Based on the following information:
283
282
  1. Comprehensive Research Summary:
@@ -607,6 +606,178 @@ else:
607
606
  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
607
 
609
608
 
609
+ ## NPCArray - NumPy for AI
610
+
611
+ `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.
612
+
613
+ ### Core Concepts
614
+ - Model arrays support vectorized operations
615
+ - Operations are lazy until `.collect()` is called (like Spark)
616
+ - Same interface works for single models (treated as length-1 arrays)
617
+ - Supports ensemble voting, consensus, evolution, and more
618
+
619
+ ### Basic Usage
620
+
621
+ ```python
622
+ from npcpy.npc_array import NPCArray
623
+
624
+ # Create array of LLMs
625
+ models = NPCArray.from_llms(
626
+ ['llama3.2', 'gemma3:1b'],
627
+ providers='ollama'
628
+ )
629
+
630
+ print(f"Model array shape: {models.shape}") # (2,)
631
+
632
+ # Inference across all models - returns shape (n_models, n_prompts)
633
+ result = models.infer("What is 2+2? Just the number.").collect()
634
+
635
+ print(f"Model 1: {result.data[0, 0]}")
636
+ print(f"Model 2: {result.data[1, 0]}")
637
+ ```
638
+
639
+ ### Lazy Chaining & Ensemble Operations
640
+
641
+ ```python
642
+ from npcpy.npc_array import NPCArray
643
+
644
+ models = NPCArray.from_llms(['llama3.2', 'gemma3:1b', 'mistral:7b'])
645
+
646
+ # Build lazy computation graph - nothing executed yet
647
+ result = (
648
+ models
649
+ .infer("Is Python compiled or interpreted? One word.")
650
+ .map(lambda r: r.strip().lower()) # Clean responses
651
+ .vote(axis=0) # Majority voting across models
652
+ )
653
+
654
+ # Show the computation plan
655
+ result.explain()
656
+
657
+ # Now execute
658
+ answer = result.collect()
659
+ print(f"Consensus: {answer.data[0]}")
660
+ ```
661
+
662
+ ### Parameter Sweeps with Meshgrid
663
+
664
+ ```python
665
+ from npcpy.npc_array import NPCArray
666
+
667
+ # Cartesian product over parameters
668
+ configs = NPCArray.meshgrid(
669
+ models=['llama3.2', 'gemma3:1b'],
670
+ temperatures=[0.0, 0.5, 1.0]
671
+ )
672
+
673
+ print(f"Config array shape: {configs.shape}") # (6,) = 2 models × 3 temps
674
+
675
+ # Run inference with each config
676
+ result = configs.infer("Complete: The quick brown fox").collect()
677
+ ```
678
+
679
+ ### Matrix Sampling with get_llm_response
680
+
681
+ The `get_llm_response` function supports `matrix` and `n_samples` parameters for exploration:
682
+
683
+ ```python
684
+ from npcpy.llm_funcs import get_llm_response
685
+
686
+ # Matrix parameter - cartesian product over specified params
687
+ result = get_llm_response(
688
+ "Write a creative opening line.",
689
+ matrix={
690
+ 'model': ['llama3.2', 'gemma3:1b'],
691
+ 'temperature': [0.5, 1.0]
692
+ }
693
+ )
694
+ print(f"Number of runs: {len(result['runs'])}") # 4 = 2×2
695
+
696
+ # n_samples - multiple samples from same config
697
+ result = get_llm_response(
698
+ "Pick a random number 1-100.",
699
+ model='llama3.2',
700
+ n_samples=5
701
+ )
702
+ print(f"Samples: {[r['response'] for r in result['runs']]}")
703
+
704
+ # Combine both for full exploration
705
+ result = get_llm_response(
706
+ "Flip a coin: heads or tails?",
707
+ matrix={'model': ['llama3.2', 'gemma3:1b']},
708
+ n_samples=3 # 2 models × 3 samples = 6 runs
709
+ )
710
+ ```
711
+
712
+ ### sklearn Integration
713
+
714
+ ```python
715
+ from npcpy.npc_array import NPCArray
716
+ from sklearn.ensemble import RandomForestClassifier
717
+ from sklearn.linear_model import LogisticRegression
718
+ import numpy as np
719
+
720
+ # Create sample data
721
+ X_train = np.random.randn(100, 4)
722
+ y_train = (X_train[:, 0] > 0).astype(int)
723
+
724
+ # Pre-fit models
725
+ rf = RandomForestClassifier(n_estimators=10).fit(X_train, y_train)
726
+ lr = LogisticRegression().fit(X_train, y_train)
727
+
728
+ # Create array from fitted models
729
+ models = NPCArray.from_sklearn([rf, lr])
730
+
731
+ # Vectorized prediction
732
+ X_test = np.random.randn(20, 4)
733
+ predictions = models.predict(X_test).collect()
734
+
735
+ print(f"RF predictions: {predictions.data[0]}")
736
+ print(f"LR predictions: {predictions.data[1]}")
737
+ ```
738
+
739
+ ### ML Functions with Grid Search
740
+
741
+ ```python
742
+ from npcpy.ml_funcs import fit_model, score_model, ensemble_predict
743
+
744
+ # Grid search via matrix parameter
745
+ result = fit_model(
746
+ X_train, y_train,
747
+ model='RandomForestClassifier',
748
+ matrix={
749
+ 'n_estimators': [10, 50, 100],
750
+ 'max_depth': [3, 5, 10]
751
+ }
752
+ )
753
+
754
+ print(f"Fitted {len(result['models'])} model configurations")
755
+
756
+ # Ensemble voting with multiple models
757
+ predictions = ensemble_predict(X_test, result['models'], method='vote')
758
+ ```
759
+
760
+ ### Quick Utilities
761
+
762
+ ```python
763
+ from npcpy.npc_array import infer_matrix, ensemble_vote
764
+
765
+ # Quick matrix inference
766
+ result = infer_matrix(
767
+ prompts=["Hello", "Goodbye"],
768
+ models=['llama3.2', 'gemma3:1b']
769
+ )
770
+
771
+ # Quick ensemble vote
772
+ answer = ensemble_vote(
773
+ "What is the capital of France? One word.",
774
+ models=['llama3.2', 'gemma3:1b']
775
+ )
776
+ print(f"Voted answer: {answer}")
777
+ ```
778
+
779
+ See `examples/npc_array_examples.py` for more comprehensive examples.
780
+
610
781
 
611
782
  ## Serving an NPC Team
612
783
 
@@ -1,10 +1,12 @@
1
- npcpy/__init__.py,sha256=9imxFtK74_6Rw9rz0kyMnZYl_voPb569tkTlYLt0Urg,131
2
- npcpy/llm_funcs.py,sha256=RtZAtX1_nvfn-X3IHVyQggDBXDzGxKEix_sS_iliNN0,87172
1
+ npcpy/__init__.py,sha256=uJcJGjR1mWvE69GySNAufkgiRwJA28zdObDBWaxp0tY,505
2
+ npcpy/llm_funcs.py,sha256=KJpjN6q5iW_qdUfgt4tzYENCAu86376io8eFZ7wp76Y,78081
3
3
  npcpy/main.py,sha256=RWoRIj6VQLxKdOKvdVyaq2kwG35oRpeXPvp1CAAoG-w,81
4
- npcpy/npc_compiler.py,sha256=mMYokNIlROl10NKsLJA_4wgO5rRr6tJQNRUwM13cnx8,101078
5
- npcpy/npc_sysenv.py,sha256=t9AswM-9_P2NaGsnlzTMc2hUfdSthi9ofbud6F1G7LM,35974
4
+ npcpy/ml_funcs.py,sha256=UI7k7JR4XOH_VXR-xxLaO4r9Kyx_jBaEnp3TUIY7ZLQ,22657
5
+ npcpy/npc_array.py,sha256=fVTxcMiXV-lvltmuwaRnTU9D3ikPq3-7k5wzp7MA5OY,40224
6
+ npcpy/npc_compiler.py,sha256=956ZMSSrYmVRp52-A4-wasg6wey3QIWHGGirDL-dW8o,111498
7
+ npcpy/npc_sysenv.py,sha256=rtE3KrXvIuOEpMq1CW5eK5K0o3f6mXagNXCeMnhHob4,36736
6
8
  npcpy/npcs.py,sha256=eExuVsbTfrRobTRRptRpDm46jCLWUgbvy4_U7IUQo-c,744
7
- npcpy/serve.py,sha256=3QU62spZ-yyWqWYb1iV_22Ir7shqMUSH_TKhvt8Ljkw,169725
9
+ npcpy/serve.py,sha256=wbIXUFlmfKg72ZYoX_cBJ8FVDFabHsGnbMwMIj-412Y,174839
8
10
  npcpy/tools.py,sha256=A5_oVmZkzGnI3BI-NmneuxeXQq-r29PbpAZP4nV4jrc,5303
9
11
  npcpy/data/__init__.py,sha256=1tcoChR-Hjn905JDLqaW9ElRmcISCTJdE7BGXPlym2Q,642
10
12
  npcpy/data/audio.py,sha256=3qryGXnWHa4JFMonjuX-lf0fCrF8jmbHe7mHAuOdua0,12397
@@ -25,9 +27,9 @@ npcpy/ft/usft.py,sha256=O025GGYGZQf2ZVLowyAmBwh5bJyuy2dUAM6v03YcboY,3435
25
27
  npcpy/gen/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
26
28
  npcpy/gen/audio_gen.py,sha256=w4toESu7nmli1T5FOwRRCGC_QK9W-SMWknYYkbRv9jE,635
27
29
  npcpy/gen/embeddings.py,sha256=QStTJ2ELiC379OEZsLEgGGIIFD267Y8zQchs7HRn2Zg,2089
28
- npcpy/gen/image_gen.py,sha256=PFaJAjMB0P1DV_x4tWXh25qGyjkntRejFLBnVPKSsqY,21730
30
+ npcpy/gen/image_gen.py,sha256=VflU_wJsKWJarOVwZtL2M8ymDFfKNz8WX66Rwk4obeo,21778
29
31
  npcpy/gen/ocr.py,sha256=rgmXWHrCYX1Po-qG_LrNFbVYEZ8aaupxFTgparcoB_Y,6554
30
- npcpy/gen/response.py,sha256=6iAOi4hxUxkTZ1d2suBUASOssT6pQnr3HFwZWrvmATg,31925
32
+ npcpy/gen/response.py,sha256=xSFHNZTDsebFo_nptWwSahpCU9_4pbCqabMFZ3X4_Bg,39979
31
33
  npcpy/gen/video_gen.py,sha256=RFi3Zcq_Hn3HIcfoF3mijQ6G7RYFZaM_9pjPTh-8E64,3239
32
34
  npcpy/memory/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
33
35
  npcpy/memory/command_history.py,sha256=vWzZ4F4o0XOSHn50SkdP885jG1aZIZvfcPAh8EZWlQk,54497
@@ -42,14 +44,14 @@ npcpy/sql/ai_function_tools.py,sha256=ZCpjVHtaMRdL2dXxbQy5NhhjtPrVViGT1wyEl8ADrk
42
44
  npcpy/sql/database_ai_adapters.py,sha256=CMlNGOhmJZhGB47RPvLIMqB61m_eYPVg1lwx42_b0jQ,6865
43
45
  npcpy/sql/database_ai_functions.py,sha256=XQCmaFOE1lNCnwrLTNpotYOlv6sx41bb8hxZI_sqpy8,6335
44
46
  npcpy/sql/model_runner.py,sha256=hJZ7hx2mwI-8DAh47Q6BwOsRjx30-HzebL4ajEUO4HA,5734
45
- npcpy/sql/npcsql.py,sha256=-PmV7AXSKwRog4gPHTeHzmvPrnDZOiccjgkUGv4DwEU,35614
47
+ npcpy/sql/npcsql.py,sha256=YRBbcsMPNWLhzZqoF0wAL2MaT6OOc0wh33Z0hb01rjc,36591
46
48
  npcpy/sql/sql_model_compiler.py,sha256=G-0dpTlgzc-dXy9YEsdWGjO8xaQ3jFNbc6oUja1Ef4M,5364
47
49
  npcpy/work/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
48
50
  npcpy/work/desktop.py,sha256=F3I8mUtJp6LAkXodsh8hGZIncoads6c_2Utty-0EdDA,2986
49
51
  npcpy/work/plan.py,sha256=QyUwg8vElWiHuoS-xK4jXTxxHvkMD3VkaCEsCmrEPQk,8300
50
52
  npcpy/work/trigger.py,sha256=P1Y8u1wQRsS2WACims_2IdkBEar-iBQix-2TDWoW0OM,9948
51
- npcpy-1.2.36.dist-info/licenses/LICENSE,sha256=j0YPvce7Ng9e32zYOu0EmXjXeJ0Nwawd0RA3uSGGH4E,1070
52
- npcpy-1.2.36.dist-info/METADATA,sha256=TclDTn6w0nbPuQXtbOTFwxfpHVgjYYc49EVDHTiMW64,33537
53
- npcpy-1.2.36.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
54
- npcpy-1.2.36.dist-info/top_level.txt,sha256=g1pbSvrOOncB74Bg5-J0Olg4V0A5VzDw-Xz5YObq8BU,6
55
- npcpy-1.2.36.dist-info/RECORD,,
53
+ npcpy-1.3.1.dist-info/licenses/LICENSE,sha256=j0YPvce7Ng9e32zYOu0EmXjXeJ0Nwawd0RA3uSGGH4E,1070
54
+ npcpy-1.3.1.dist-info/METADATA,sha256=dbTBVm4ZMDwwnGkOC3Ahwwhf9OpcecBO_Tdww1ToUwE,37884
55
+ npcpy-1.3.1.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
56
+ npcpy-1.3.1.dist-info/top_level.txt,sha256=g1pbSvrOOncB74Bg5-J0Olg4V0A5VzDw-Xz5YObq8BU,6
57
+ npcpy-1.3.1.dist-info/RECORD,,
File without changes