An Injected instance can be run from CLI with the following command.
python -m pinjected run [path of an Injected variable] [optional path of a Design variable] [Optional overrides for a design] --additional-bindings- Variable Path:
your.package.var.name - Design Path:
your.package.design.name - Optional Overrides:
your.package.override_design.name
The main command to run an injected variable.
python -m pinjected run [path of an Injected variable] [optional path of a Design variable] [Optional overrides for a design] --additional-bindingsGenerates a human-readable description of the dependency graph for a variable, showing dependencies with their documentation.
python -m pinjected describe [path of an Injected variable] [optional path of a Design variable] [additional parameters]This command visualizes:
- The dependency tree structure
- Documentation for each dependency
- Relationships between dependencies
It's useful for understanding complex dependency relationships and their purpose.
python -m pinjected my.package.instance --name hello --yourconfig anystringThis CLI will parse any additional keyword arguments into a call of design internally to be appended to the design
running this injected instance.
Which is equivalent to running following script:
from my.package import instance
d = design(
name='dummy',
yourconfig='dummy'
) + design(
name = 'hello',
yourconfig = 'anystring'
)
d.provide(instance)We can use {package.var.name} to tell the cli that the additional bindings are to be imported from the specified path.
Example:
# my.module2.py
from pinjected import instance
@instance
def load_hostname():
import socket
return socket.gethostname()# my.module.py
from pinjected import injected
@injected
def print_hostname(hostname):
print(hostname)python -m pinjected run my.module.print_hostname --hostname "{my.module2.load_hostname}"This is useful for switching complicated injected instances for running the target. The complicated injected instances can be trained ML models, etc.
Example2:
# some.llm.module.py
from pinjected import injected
@injected
def llm_openai(openai_api_key, /, prompt):
return "call open ai api with prompt..."
@injected
def llm_azure(azure_api_key, /, prompt):
return "call azure api with prompt..."
@injected
def llm_llama(llama_model_on_gpu, configs, /, prompt):
return llama_model_on_gpu(prompt, configs)
@injected
def chat(llm, /, prompt):
return llm(prompt)python -m pinjected run some.llm.module.chat --llm="{some.llm.module.llm_openai}" "hello!"Now we can switch llm with llm_openai, llm_azure, llm_llama... by specifying a importable variable path.
pinjected run reads dependency configurations from two sources:
__design__variables in__pinjected__.pyfiles (recommended)__meta_design__variables in module files (legacy, being deprecated)
The recommended approach is to place __pinjected__.py files in your package directories:
- some_package
| __init__.py
| __pinjected__.py [-- contains __design__
| module1
| | __init__.py
| | __pinjected__.py [-- contains __design__
| | util.py
When running "python -m pinjected run some_package.module1.util.run", all __design__ variables from __pinjected__.py files in parent packages will be loaded and concatenated.
# Example __pinjected__.py file
from pinjected import design
__design__ = design(
config_key="config_value",
another_key="another_value"
)The older approach using __meta_design__ variables in module files is being deprecated:
- some_package
| __init__.py [-- can contain __meta_design__
| module1
| | __init__.py [-- can contain __meta_design__
| | util.py [-- can contain __meta_design__
When running with this approach, all __meta_design__ variables in parent packages will be loaded and concatenated:
meta_design = some_package.__meta_design__ + some_package.module1.__meta_design + some_package.module1.util.__meta_design__
overrides = meta_design.provide('overrides')
default_design = import_if_exist(meta_design['default_design_path'])
g = (default_design + overrides).to_graph()
g[some_package.module1.util.run]It's recommended to migrate to the new __design__ in __pinjected__.py files approach.
Additionaly, we can place .pinjected.py file in the current directly or the home directory. a global variable named ' default_design' and 'overrides' will be automatically imported, then prepended and appended to the design before running the target.
This is convinient for specifying user specific injection variables such as api keys, or some user specific functions.