-
Notifications
You must be signed in to change notification settings - Fork 2.7k
feat: dynamic invocation definitions #4334
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
# Conflicts: # invokeai/app/api_app.py
| def reload_nodes(path: str, codefile: jurigged.CodeFile): | ||
| """Callback function for jurigged post-run events.""" | ||
| # Things we have access to here: | ||
| # codefile.module:module - the module object associated with this file | ||
| # codefile.module_name:str - the full module name (its key in sys.modules) | ||
| # codefile.root:ModuleCode - an AST of the current source |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Here, I gave you a function that will run after jurigged reloads anything. I haven't yet hooked it up to any of the update functions in this PR.
… do the other import
|
After our talk about Pydantic and its unions today, I had another go at this, and found it a surprisingly tough nut to crack. Brain dumping here: We need two things to happen when we add a new invocation type:
I think the first one is easy. You can add validators to any Pydantic model, and though they're called "validator" that's where instantiation happens. It may be that all we need to do is pop in a validator that can create things of these late-discovered classes, instead of being limited to the ones known at time of first import. The place I got stuck was on the schema. I figured there ought to be a way to override the schema generation too, maybe with some the problemsThe parts that make this sticky are:
other ideas
|
|
many of these ideas get way deeper into the weeds of Pydantic internals than I wanted to be. It may be a bad investment to spend much more time on that with the Pydantic 1.x API; maybe it's something to schedule for after upgrading to the current versions of Pydantic + FastAPI. |
|
Great detective work! I agree that we should wait for pydantic v2 to spend too much time on this, unless it really strikes your fancy. (not only are we on crusty pydantic v1, we are on fastapi 0.88 or something legitimately ancient - we are really due for an upgrade, but there are some puzzles to solve along the way to being up to date) |
|
Just curious - what are the issues with updating at present? |
|
@lillekemiker |
|
This is considerably simpler in pydantic v2: from typing import Annotated, Literal, Union
from pydantic import BaseModel, Field, ValidationError
from pydantic.fields import FieldInfo
class Type1(BaseModel):
type: Literal["type1"] = "type1"
class Type2(BaseModel):
type: Literal["type2"] = "type2"
class Type3(BaseModel):
type: Literal["type3"] = "type3"
SomeUnion = Union[Type1, Type2]
class Model(BaseModel):
a: Annotated[SomeUnion, Field(discriminator="type")] = Field(description="test dynamic union")
b: str = Field(description="string")
@classmethod
def update_union(cls):
SomeUnion = Union[Type1,Type2,Type3]
cls.model_fields['a'] = FieldInfo.from_annotated_attribute(Annotated[SomeUnion, Field(discriminator="type")], Field(description="test dynamic union"))
cls.model_rebuild(force=True)
Model(a=Type1(), b="test")
try:
Model(a=Type3(), b="test")
except ValidationError:
print("Invalid :(")
Model.update_union()
print("Union updated")
Model(a=Type3(), b="test")
print("Valid :)")With the improvements made in #4758 to registration of invocations, this shouldn't be a blocker. Due to circular dependencies, I don't think we can automatically call this method during registration - it needs to be called outside it, so somewhere in |
|
@psychedelicious do you think we could get this in for 3.4 with the pydantic update out of the way? |
Experimental - add new nodes to pydantic models at runtime to allow for hot-loading of nodes.