vibe-aigc 0.6.2__py3-none-any.whl → 0.6.3__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.
- vibe_aigc/tools.py +14 -2
- vibe_aigc/tools_comfyui.py +271 -0
- {vibe_aigc-0.6.2.dist-info → vibe_aigc-0.6.3.dist-info}/METADATA +1 -1
- {vibe_aigc-0.6.2.dist-info → vibe_aigc-0.6.3.dist-info}/RECORD +8 -7
- {vibe_aigc-0.6.2.dist-info → vibe_aigc-0.6.3.dist-info}/WHEEL +0 -0
- {vibe_aigc-0.6.2.dist-info → vibe_aigc-0.6.3.dist-info}/entry_points.txt +0 -0
- {vibe_aigc-0.6.2.dist-info → vibe_aigc-0.6.3.dist-info}/licenses/LICENSE +0 -0
- {vibe_aigc-0.6.2.dist-info → vibe_aigc-0.6.3.dist-info}/top_level.txt +0 -0
vibe_aigc/tools.py
CHANGED
|
@@ -496,8 +496,12 @@ class ToolRegistry:
|
|
|
496
496
|
return "\n".join(lines)
|
|
497
497
|
|
|
498
498
|
|
|
499
|
-
def create_default_registry() -> ToolRegistry:
|
|
500
|
-
"""Create a registry with default tools.
|
|
499
|
+
def create_default_registry(comfyui_url: str = "http://127.0.0.1:8188") -> ToolRegistry:
|
|
500
|
+
"""Create a registry with default tools.
|
|
501
|
+
|
|
502
|
+
Args:
|
|
503
|
+
comfyui_url: URL for ComfyUI server (for image/video generation)
|
|
504
|
+
"""
|
|
501
505
|
registry = ToolRegistry()
|
|
502
506
|
|
|
503
507
|
# Register built-in tools
|
|
@@ -505,4 +509,12 @@ def create_default_registry() -> ToolRegistry:
|
|
|
505
509
|
registry.register(TemplateTool())
|
|
506
510
|
registry.register(CombineTool())
|
|
507
511
|
|
|
512
|
+
# Register ComfyUI-based generation tools (Paper Section 5.4)
|
|
513
|
+
try:
|
|
514
|
+
from .tools_comfyui import create_comfyui_tools
|
|
515
|
+
for tool in create_comfyui_tools(comfyui_url):
|
|
516
|
+
registry.register(tool)
|
|
517
|
+
except ImportError:
|
|
518
|
+
pass # ComfyUI tools optional
|
|
519
|
+
|
|
508
520
|
return registry
|
|
@@ -0,0 +1,271 @@
|
|
|
1
|
+
"""
|
|
2
|
+
ComfyUI Generation Tools - Image and Video Generation via VibeBackend.
|
|
3
|
+
|
|
4
|
+
Integrates the VibeBackend into the Paper's tool architecture (Section 5.4):
|
|
5
|
+
"The Planner traverses the system's atomic tool library...to select
|
|
6
|
+
the optimal ensemble of components."
|
|
7
|
+
|
|
8
|
+
This makes ComfyUI-based generation available to MetaPlanner as atomic tools.
|
|
9
|
+
"""
|
|
10
|
+
|
|
11
|
+
from typing import Dict, Any, Optional
|
|
12
|
+
from dataclasses import dataclass
|
|
13
|
+
|
|
14
|
+
from .tools import BaseTool, ToolSpec, ToolResult, ToolCategory
|
|
15
|
+
from .vibe_backend import VibeBackend, GenerationRequest, GenerationResult
|
|
16
|
+
from .discovery import Capability
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
class ImageGenerationTool(BaseTool):
|
|
20
|
+
"""
|
|
21
|
+
Image generation tool using local ComfyUI.
|
|
22
|
+
|
|
23
|
+
Maps high-level image requests to VibeBackend execution.
|
|
24
|
+
MetaPlanner can use this for visual content generation.
|
|
25
|
+
"""
|
|
26
|
+
|
|
27
|
+
def __init__(self, comfyui_url: str = "http://127.0.0.1:8188"):
|
|
28
|
+
self.comfyui_url = comfyui_url
|
|
29
|
+
self._backend: Optional[VibeBackend] = None
|
|
30
|
+
|
|
31
|
+
@property
|
|
32
|
+
def spec(self) -> ToolSpec:
|
|
33
|
+
return ToolSpec(
|
|
34
|
+
name="image_generation",
|
|
35
|
+
description="Generate images using local AI models (FLUX, SD, etc.)",
|
|
36
|
+
category=ToolCategory.IMAGE,
|
|
37
|
+
input_schema={
|
|
38
|
+
"type": "object",
|
|
39
|
+
"required": ["prompt"],
|
|
40
|
+
"properties": {
|
|
41
|
+
"prompt": {"type": "string", "description": "Image description"},
|
|
42
|
+
"negative_prompt": {"type": "string", "description": "What to avoid"},
|
|
43
|
+
"style": {"type": "string", "description": "Visual style hints"},
|
|
44
|
+
"width": {"type": "integer", "default": 768},
|
|
45
|
+
"height": {"type": "integer", "default": 512},
|
|
46
|
+
"steps": {"type": "integer", "default": 20},
|
|
47
|
+
"cfg": {"type": "number", "default": 7.0}
|
|
48
|
+
}
|
|
49
|
+
},
|
|
50
|
+
output_schema={
|
|
51
|
+
"type": "object",
|
|
52
|
+
"properties": {
|
|
53
|
+
"image_url": {"type": "string"},
|
|
54
|
+
"quality_score": {"type": "number"},
|
|
55
|
+
"feedback": {"type": "string"}
|
|
56
|
+
}
|
|
57
|
+
},
|
|
58
|
+
examples=[
|
|
59
|
+
{
|
|
60
|
+
"input": {"prompt": "cyberpunk cityscape at night, neon lights, rain"},
|
|
61
|
+
"output": {"image_url": "http://...", "quality_score": 7.5}
|
|
62
|
+
}
|
|
63
|
+
]
|
|
64
|
+
)
|
|
65
|
+
|
|
66
|
+
async def _ensure_backend(self) -> VibeBackend:
|
|
67
|
+
"""Lazily initialize backend."""
|
|
68
|
+
if self._backend is None:
|
|
69
|
+
self._backend = VibeBackend(
|
|
70
|
+
comfyui_url=self.comfyui_url,
|
|
71
|
+
enable_vlm=True,
|
|
72
|
+
max_attempts=2,
|
|
73
|
+
quality_threshold=6.0
|
|
74
|
+
)
|
|
75
|
+
await self._backend.initialize()
|
|
76
|
+
return self._backend
|
|
77
|
+
|
|
78
|
+
async def execute(
|
|
79
|
+
self,
|
|
80
|
+
inputs: Dict[str, Any],
|
|
81
|
+
context: Optional[Dict[str, Any]] = None
|
|
82
|
+
) -> ToolResult:
|
|
83
|
+
"""Generate an image based on inputs."""
|
|
84
|
+
try:
|
|
85
|
+
backend = await self._ensure_backend()
|
|
86
|
+
|
|
87
|
+
# Build prompt from inputs + context (knowledge base hints)
|
|
88
|
+
prompt = inputs.get("prompt", "")
|
|
89
|
+
style = inputs.get("style", "")
|
|
90
|
+
|
|
91
|
+
# If knowledge base provided style hints, incorporate them
|
|
92
|
+
if context and "technical_specs" in context:
|
|
93
|
+
specs = context["technical_specs"]
|
|
94
|
+
if "lighting" in specs:
|
|
95
|
+
prompt += f", {', '.join(specs['lighting'])}"
|
|
96
|
+
if "color_grading" in specs:
|
|
97
|
+
prompt += f", {specs['color_grading']}"
|
|
98
|
+
|
|
99
|
+
if style:
|
|
100
|
+
prompt = f"{prompt}, {style}"
|
|
101
|
+
|
|
102
|
+
result = await backend.generate(GenerationRequest(
|
|
103
|
+
prompt=prompt,
|
|
104
|
+
capability=Capability.TEXT_TO_IMAGE,
|
|
105
|
+
negative_prompt=inputs.get("negative_prompt", ""),
|
|
106
|
+
width=inputs.get("width", 768),
|
|
107
|
+
height=inputs.get("height", 512),
|
|
108
|
+
steps=inputs.get("steps", 20),
|
|
109
|
+
cfg=inputs.get("cfg", 7.0)
|
|
110
|
+
))
|
|
111
|
+
|
|
112
|
+
if result.success:
|
|
113
|
+
return ToolResult(
|
|
114
|
+
success=True,
|
|
115
|
+
output={
|
|
116
|
+
"image_url": result.output_url,
|
|
117
|
+
"quality_score": result.quality_score,
|
|
118
|
+
"feedback": result.feedback,
|
|
119
|
+
"strengths": result.strengths,
|
|
120
|
+
"weaknesses": result.weaknesses
|
|
121
|
+
},
|
|
122
|
+
metadata={
|
|
123
|
+
"model_used": result.model_used,
|
|
124
|
+
"attempts": result.attempts
|
|
125
|
+
}
|
|
126
|
+
)
|
|
127
|
+
else:
|
|
128
|
+
return ToolResult(
|
|
129
|
+
success=False,
|
|
130
|
+
output=None,
|
|
131
|
+
error=result.error
|
|
132
|
+
)
|
|
133
|
+
except Exception as e:
|
|
134
|
+
return ToolResult(
|
|
135
|
+
success=False,
|
|
136
|
+
output=None,
|
|
137
|
+
error=str(e)
|
|
138
|
+
)
|
|
139
|
+
|
|
140
|
+
|
|
141
|
+
class VideoGenerationTool(BaseTool):
|
|
142
|
+
"""
|
|
143
|
+
Video generation tool using local ComfyUI.
|
|
144
|
+
|
|
145
|
+
Uses the I2V pipeline: FLUX → Wan I2V animation.
|
|
146
|
+
MetaPlanner can use this for motion content.
|
|
147
|
+
"""
|
|
148
|
+
|
|
149
|
+
def __init__(self, comfyui_url: str = "http://127.0.0.1:8188"):
|
|
150
|
+
self.comfyui_url = comfyui_url
|
|
151
|
+
self._backend: Optional[VibeBackend] = None
|
|
152
|
+
|
|
153
|
+
@property
|
|
154
|
+
def spec(self) -> ToolSpec:
|
|
155
|
+
return ToolSpec(
|
|
156
|
+
name="video_generation",
|
|
157
|
+
description="Generate videos using local AI models (FLUX + Wan I2V)",
|
|
158
|
+
category=ToolCategory.VIDEO,
|
|
159
|
+
input_schema={
|
|
160
|
+
"type": "object",
|
|
161
|
+
"required": ["prompt"],
|
|
162
|
+
"properties": {
|
|
163
|
+
"prompt": {"type": "string", "description": "Video description"},
|
|
164
|
+
"negative_prompt": {"type": "string", "description": "What to avoid"},
|
|
165
|
+
"style": {"type": "string", "description": "Visual style hints"},
|
|
166
|
+
"motion": {"type": "string", "description": "Motion description"},
|
|
167
|
+
"width": {"type": "integer", "default": 832},
|
|
168
|
+
"height": {"type": "integer", "default": 480},
|
|
169
|
+
"frames": {"type": "integer", "default": 33},
|
|
170
|
+
"fps": {"type": "integer", "default": 16}
|
|
171
|
+
}
|
|
172
|
+
},
|
|
173
|
+
output_schema={
|
|
174
|
+
"type": "object",
|
|
175
|
+
"properties": {
|
|
176
|
+
"video_url": {"type": "string"},
|
|
177
|
+
"duration_seconds": {"type": "number"}
|
|
178
|
+
}
|
|
179
|
+
},
|
|
180
|
+
examples=[
|
|
181
|
+
{
|
|
182
|
+
"input": {"prompt": "samurai walking through rain", "frames": 33},
|
|
183
|
+
"output": {"video_url": "http://...", "duration_seconds": 2.0}
|
|
184
|
+
}
|
|
185
|
+
]
|
|
186
|
+
)
|
|
187
|
+
|
|
188
|
+
async def _ensure_backend(self) -> VibeBackend:
|
|
189
|
+
"""Lazily initialize backend."""
|
|
190
|
+
if self._backend is None:
|
|
191
|
+
self._backend = VibeBackend(
|
|
192
|
+
comfyui_url=self.comfyui_url,
|
|
193
|
+
enable_vlm=False, # VLM slower for video
|
|
194
|
+
max_attempts=1
|
|
195
|
+
)
|
|
196
|
+
await self._backend.initialize()
|
|
197
|
+
return self._backend
|
|
198
|
+
|
|
199
|
+
async def execute(
|
|
200
|
+
self,
|
|
201
|
+
inputs: Dict[str, Any],
|
|
202
|
+
context: Optional[Dict[str, Any]] = None
|
|
203
|
+
) -> ToolResult:
|
|
204
|
+
"""Generate a video based on inputs."""
|
|
205
|
+
try:
|
|
206
|
+
backend = await self._ensure_backend()
|
|
207
|
+
|
|
208
|
+
# Build prompt
|
|
209
|
+
prompt = inputs.get("prompt", "")
|
|
210
|
+
style = inputs.get("style", "")
|
|
211
|
+
motion = inputs.get("motion", "")
|
|
212
|
+
|
|
213
|
+
# Incorporate knowledge base hints
|
|
214
|
+
if context and "technical_specs" in context:
|
|
215
|
+
specs = context["technical_specs"]
|
|
216
|
+
if "camera" in specs:
|
|
217
|
+
prompt += f", {', '.join(specs['camera'][:2])}"
|
|
218
|
+
if "editing" in specs:
|
|
219
|
+
motion = motion or specs["editing"][0] if specs["editing"] else ""
|
|
220
|
+
|
|
221
|
+
if style:
|
|
222
|
+
prompt = f"{prompt}, {style}"
|
|
223
|
+
if motion:
|
|
224
|
+
prompt = f"{prompt}, {motion}"
|
|
225
|
+
|
|
226
|
+
frames = inputs.get("frames", 33)
|
|
227
|
+
fps = inputs.get("fps", 16)
|
|
228
|
+
|
|
229
|
+
result = await backend.generate(GenerationRequest(
|
|
230
|
+
prompt=prompt,
|
|
231
|
+
capability=Capability.TEXT_TO_VIDEO,
|
|
232
|
+
negative_prompt=inputs.get("negative_prompt", ""),
|
|
233
|
+
width=inputs.get("width", 832),
|
|
234
|
+
height=inputs.get("height", 480),
|
|
235
|
+
frames=frames,
|
|
236
|
+
steps=20,
|
|
237
|
+
cfg=5.0
|
|
238
|
+
))
|
|
239
|
+
|
|
240
|
+
if result.success:
|
|
241
|
+
return ToolResult(
|
|
242
|
+
success=True,
|
|
243
|
+
output={
|
|
244
|
+
"video_url": result.output_url,
|
|
245
|
+
"duration_seconds": frames / fps
|
|
246
|
+
},
|
|
247
|
+
metadata={
|
|
248
|
+
"frames": frames,
|
|
249
|
+
"fps": fps
|
|
250
|
+
}
|
|
251
|
+
)
|
|
252
|
+
else:
|
|
253
|
+
return ToolResult(
|
|
254
|
+
success=False,
|
|
255
|
+
output=None,
|
|
256
|
+
error=result.error
|
|
257
|
+
)
|
|
258
|
+
except Exception as e:
|
|
259
|
+
return ToolResult(
|
|
260
|
+
success=False,
|
|
261
|
+
output=None,
|
|
262
|
+
error=str(e)
|
|
263
|
+
)
|
|
264
|
+
|
|
265
|
+
|
|
266
|
+
def create_comfyui_tools(comfyui_url: str = "http://127.0.0.1:8188") -> list:
|
|
267
|
+
"""Create ComfyUI-based generation tools."""
|
|
268
|
+
return [
|
|
269
|
+
ImageGenerationTool(comfyui_url=comfyui_url),
|
|
270
|
+
VideoGenerationTool(comfyui_url=comfyui_url)
|
|
271
|
+
]
|
|
@@ -16,7 +16,8 @@ vibe_aigc/models.py,sha256=wIwlN_NDL_72YXRq3Igi5X5fx1ZFGG7ER6pO5MdL4-I,2408
|
|
|
16
16
|
vibe_aigc/mv_pipeline.py,sha256=OvVnlSM8iPjrT5qmhE47p6-shKOAxN7_XqsQneuqLkk,25303
|
|
17
17
|
vibe_aigc/persistence.py,sha256=inrJQjmCK4LighxQSmJorR6c7OvRzx-cmEb5HCQS9PY,10614
|
|
18
18
|
vibe_aigc/planner.py,sha256=hmnASmofpahNuF9ei_0DxzHxm23vYjF67u-SB_G5EcU,33129
|
|
19
|
-
vibe_aigc/tools.py,sha256=
|
|
19
|
+
vibe_aigc/tools.py,sha256=Ix0JKwCATtcZykG9F3gK0gM9zw9vu_4mO_NHxkUxc-s,15997
|
|
20
|
+
vibe_aigc/tools_comfyui.py,sha256=sHe6bhYegrm2AAPzDuYyL4vcAJe_NG34vqjrLbovVX8,9979
|
|
20
21
|
vibe_aigc/tools_multimodal.py,sha256=asSJJqF0hrD9uNiYpuieVY-lbgEXjbK3UjT20nX2Lig,20405
|
|
21
22
|
vibe_aigc/vibe_backend.py,sha256=LUm9t3JeGfezJTjau9XAQeRN_DmHrPX2PCjNRhGE4lQ,23808
|
|
22
23
|
vibe_aigc/video.py,sha256=0fg8RUpEsaJqDskAPiGP8yuyQDVCUvIy-uLScq_BOwg,14111
|
|
@@ -28,9 +29,9 @@ vibe_aigc/workflow_executor.py,sha256=mfYLOTfPmI7Upooxy07nPmlbZ-HZAfC18IaNW80G31
|
|
|
28
29
|
vibe_aigc/workflow_registry.py,sha256=Z6gB1cA366LXqHcfqBF1od_8ySxAOt5RpKKaaZPqqUo,22359
|
|
29
30
|
vibe_aigc/workflow_strategies.py,sha256=i_qqUrn-2F6lT9dNyFdTdy0NzE8ZnRNxAMl6zrOAtD8,26148
|
|
30
31
|
vibe_aigc/workflows.py,sha256=uk7RjNVow6eimEdqfVQFDtLgHSkg0LUjSoa2N7C47u0,13886
|
|
31
|
-
vibe_aigc-0.6.
|
|
32
|
-
vibe_aigc-0.6.
|
|
33
|
-
vibe_aigc-0.6.
|
|
34
|
-
vibe_aigc-0.6.
|
|
35
|
-
vibe_aigc-0.6.
|
|
36
|
-
vibe_aigc-0.6.
|
|
32
|
+
vibe_aigc-0.6.3.dist-info/licenses/LICENSE,sha256=Ir4dCTvOsbfoiOh9vYbhIKDH59S7J6qhJYZmHHICoKY,1079
|
|
33
|
+
vibe_aigc-0.6.3.dist-info/METADATA,sha256=5TjNBFqxPDHGzXA5N-ihp-ojTmvgGm4Z-aaSmAzLyzk,6604
|
|
34
|
+
vibe_aigc-0.6.3.dist-info/WHEEL,sha256=wUyA8OaulRlbfwMtmQsvNngGrxQHAvkKcvRmdizlJi0,92
|
|
35
|
+
vibe_aigc-0.6.3.dist-info/entry_points.txt,sha256=2htp4yXJMvCAQXTB39XWWwbBPP3MYUYXsqlwMeQsd7o,49
|
|
36
|
+
vibe_aigc-0.6.3.dist-info/top_level.txt,sha256=Cpjz8X0WEhnhaigqxmsZSl9VxduaDspj7WuVUGGLeao,10
|
|
37
|
+
vibe_aigc-0.6.3.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|