Skip to content

Commit 715f8f8

Browse files
authored
Test Release (#80)
* Fix typo in env * Change model to gemma3 * Revert wardrobe prompt change * Bump versions server * Fix ollama multimodal issue #78 * Add batch update script * ImageTool use png * Change tool arg name
1 parent ab3b243 commit 715f8f8

11 files changed

Lines changed: 703 additions & 428 deletions

File tree

server/agents/outfit_crew/pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ description = "outfit_crew using crewAI"
55
authors = [{ name = "Your Name", email = "you@example.com" }]
66
requires-python = ">=3.10,<3.14"
77
dependencies = [
8-
"crewai[tools]>=0.126.0,<1.0.0"
8+
"crewai[tools]>=0.140.0,<1.0.0"
99
]
1010

1111
[project.scripts]

server/agents/quiz_crew/pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ description = "quiz_crew using crewAI"
55
authors = [{ name = "Your Name", email = "you@example.com" }]
66
requires-python = ">=3.10,<3.14"
77
dependencies = [
8-
"crewai[tools]>=0.126.0,<1.0.0"
8+
"crewai[tools]>=0.140.0,<1.0.0"
99
]
1010

1111
[project.scripts]

server/agents/trend_crew/pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ description = "trend_crew using crewAI"
55
authors = [{ name = "Your Name", email = "you@example.com" }]
66
requires-python = ">=3.10,<3.14"
77
dependencies = [
8-
"crewai[tools]>=0.126.0,<1.0.0",
8+
"crewai[tools]>=0.140.0,<1.0.0",
99
"ollama>=0.5.1",
1010
]
1111

server/agents/wardrobe_crew/pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ description = "wardrobe_crew using crewAI"
55
authors = [{ name = "Your Name", email = "you@example.com" }]
66
requires-python = ">=3.10,<3.14"
77
dependencies = [
8-
"crewai[tools]>=0.126.0,<1.0.0"
8+
"crewai[tools]>=0.140.0,<1.0.0"
99
]
1010

1111
[project.scripts]
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
import base64
2+
import requests
3+
from io import BytesIO
4+
5+
from PIL import Image
6+
7+
from typing import Dict, Optional, Union
8+
9+
from pydantic import BaseModel, Field
10+
11+
from crewai.tools.base_tool import BaseTool
12+
13+
14+
class AddImageToolSchema(BaseModel):
15+
image_url: str = Field(..., description="The URL of the image to add")
16+
action: Optional[str] = Field(
17+
default=None, description="Optional context or question about the image"
18+
)
19+
20+
21+
class AddImageTool(BaseTool):
22+
"""Tool for adding images to the content"""
23+
24+
name: str = "Add image to content"
25+
description: str = "See image to understand its content, you can optionally ask a question about the image"
26+
args_schema: type[BaseModel] = AddImageToolSchema
27+
28+
def _get_base64_image(self, image_url: str) -> str:
29+
response = requests.get(image_url)
30+
buffered = BytesIO()
31+
pil_image = Image.open(BytesIO(response.content))
32+
pil_image.save(buffered, format="PNG") # You can change the format if needed
33+
img_str = base64.b64encode(buffered.getvalue()).decode("utf-8")
34+
return img_str
35+
36+
def _run(
37+
self,
38+
image_url: str,
39+
action: Optional[str] = None,
40+
**kwargs,
41+
) -> dict:
42+
base64_image = self._get_base64_image(image_url)
43+
44+
action = (
45+
action
46+
or "Please provide a detailed description of this image, including all visual elements, context, and any notable details you can observe."
47+
)
48+
content = [
49+
{"type": "text", "text": action},
50+
{
51+
"type": "image_url",
52+
"image_url": {
53+
"url": f"data:image/png;base64,{base64_image}",
54+
},
55+
},
56+
]
57+
58+
return {"role": "user", "content": content}

server/agents/wardrobe_crew/src/wardrobe_crew/crew.py

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,17 @@
33
from typing import List, Optional
44
from pydantic import BaseModel
55

6+
from wardrobe_crew.add_image_tool import AddImageTool
7+
68

79
class TagOutput(BaseModel):
810
tags: List[str]
911
description: Optional[str] = None
1012

1113

14+
add_image_tool = AddImageTool()
15+
16+
1217
@CrewBase
1318
class WardrobeCrew:
1419
"""Crew automatisch taggt Kleidung mit lokalem Ollama-LLM"""
@@ -23,17 +28,26 @@ def image_tagger(self) -> Agent:
2328
"Material und Schnitt, spezialisiert auf visuelle Analyse."
2429
),
2530
verbose=True,
26-
multimodal=True,
31+
)
32+
33+
@task
34+
def image_analyzing_task(self) -> Task:
35+
return Task(
36+
description=(
37+
"Analysiere das Bild eines Kleidungsstücks. Bild: {image_url}"
38+
),
39+
expected_output="Eine Beschreibung des Bildes mit besonderem Fokus auf das Kleidungsstück, einschließlich Stil, Farbe, Material und Schnitt.",
40+
agent=self.image_tagger(),
41+
tools=[add_image_tool],
2742
)
2843

2944
@task
3045
def tagging_task(self) -> Task:
3146
return Task(
3247
description=(
33-
"Analysiere das Bild eines Kleidungsstücks hier {image_url} und extrahiere 5–8 "
34-
"präzise Tags wie Stil, Farbe, Material und Schnitt."
48+
"Finde 5-8 Tags, die das Kleidungsstück beschreiben, basierend auf der Analyse des Bildes. "
3549
),
36-
expected_output="Ein Dictionary mit 'tags' (Liste) und optional 'description'",
50+
expected_output="Eine Liste von Tags, die das Kleidungsstück beschreiben.",
3751
agent=self.image_tagger(),
3852
output_pydantic=TagOutput,
3953
)
@@ -42,7 +56,7 @@ def tagging_task(self) -> Task:
4256
def crew(self) -> Crew:
4357
return Crew(
4458
agents=[self.image_tagger()],
45-
tasks=[self.tagging_task()],
59+
tasks=[self.image_analyzing_task(), self.tagging_task()],
4660
process=Process.sequential,
4761
verbose=True,
4862
)

server/agents/wardrobe_crew/src/wardrobe_crew/item_listener.py

Lines changed: 0 additions & 72 deletions
This file was deleted.

server/agents/wardrobe_crew/src/wardrobe_crew/main.py

Lines changed: 16 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -13,16 +13,18 @@
1313
# Replace with inputs you want to test with, it will automatically
1414
# interpolate any tasks and agents information
1515

16+
1617
def run():
1718
"""
1819
Run the crew.
1920
"""
2021
inputs = {
21-
'item_image': 'http://127.0.0.1:8090/api/files/items/xrfe7x38w1ddk95/cq5dam_web_he7e3da_1200_4vljrgza11.1200-1.avif'
22+
"image_url": "http://127.0.0.1:8090/api/files/pbc_710432678/a6g0uob9w61fjsc/bikini_ix3phjsbiy.jpg"
2223
}
23-
24+
2425
try:
25-
WardrobeCrew().crew().kickoff(inputs=inputs)
26+
result = WardrobeCrew().crew().kickoff(inputs=inputs)
27+
print(result.pydantic)
2628
except Exception as e:
2729
raise Exception(f"An error occurred while running the crew: {e}")
2830

@@ -31,16 +33,16 @@ def train():
3133
"""
3234
Train the crew for a given number of iterations.
3335
"""
34-
inputs = {
35-
"topic": "AI LLMs",
36-
'current_year': str(datetime.now().year)
37-
}
36+
inputs = {"topic": "AI LLMs", "current_year": str(datetime.now().year)}
3837
try:
39-
WardrobeCrew().crew().train(n_iterations=int(sys.argv[1]), filename=sys.argv[2], inputs=inputs)
38+
WardrobeCrew().crew().train(
39+
n_iterations=int(sys.argv[1]), filename=sys.argv[2], inputs=inputs
40+
)
4041

4142
except Exception as e:
4243
raise Exception(f"An error occurred while training the crew: {e}")
4344

45+
4446
def replay():
4547
"""
4648
Replay the crew execution from a specific task.
@@ -51,17 +53,17 @@ def replay():
5153
except Exception as e:
5254
raise Exception(f"An error occurred while replaying the crew: {e}")
5355

56+
5457
def test():
5558
"""
5659
Test the crew execution and returns the results.
5760
"""
58-
inputs = {
59-
"topic": "AI LLMs",
60-
"current_year": str(datetime.now().year)
61-
}
62-
61+
inputs = {"topic": "AI LLMs", "current_year": str(datetime.now().year)}
62+
6363
try:
64-
WardrobeCrew().crew().test(n_iterations=int(sys.argv[1]), eval_llm=sys.argv[2], inputs=inputs)
64+
WardrobeCrew().crew().test(
65+
n_iterations=int(sys.argv[1]), eval_llm=sys.argv[2], inputs=inputs
66+
)
6567

6668
except Exception as e:
6769
raise Exception(f"An error occurred while testing the crew: {e}")
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
import os
2+
import requests
3+
import json
4+
5+
from wardrobe_crew.crew import WardrobeCrew
6+
7+
POCKETBASE_URL = os.getenv("PB_URL", "http://localhost:8090")
8+
9+
print(f"Using PocketBase URL: {POCKETBASE_URL}")
10+
11+
12+
def tag_item_image(image_url):
13+
result = WardrobeCrew().crew().kickoff(inputs={"image_url": image_url})
14+
tags = result.pydantic.tags
15+
print(f"Tags for image {image_url}: {tags}")
16+
return tags
17+
18+
19+
res = requests.get(f"{POCKETBASE_URL}/api/collections/items/records")
20+
items = res.json()["items"]
21+
for item in items:
22+
if item["image"]:
23+
image_url = f"{POCKETBASE_URL}/api/files/items/{item['id']}/{item['image']}"
24+
tags = tag_item_image(image_url)
25+
requests.patch(
26+
f"{POCKETBASE_URL}/api/collections/items/records/{item['id']}",
27+
data={"tags": json.dumps(tags)},
28+
)
29+
else:
30+
print(f"Item {item['id']} has no image URL.")

server/pyproject.toml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ description = "Add your description here"
55
readme = "README.md"
66
requires-python = ">=3.13"
77
dependencies = [
8-
"fastapi[standard]>=0.115.12",
8+
"fastapi[standard]>=0.115.14",
99
"trend_crew",
1010
"wardrobe_crew",
1111
"outfit_crew",
@@ -15,15 +15,15 @@ dependencies = [
1515

1616
[dependency-groups]
1717
dev = [
18-
"ruff>=0.11.11",
18+
"ruff>=0.12.2",
1919
]
2020

2121
[tool.uv.sources]
2222
trend_crew = { workspace = true }
2323
wardrobe_crew = { workspace = true }
2424
outfit_crew = { workspace = true }
2525
quiz_crew = { workspace = true }
26-
litellm = { git = "https://github.com/otjamin/litellm", tag = "v1.72.0-stable.1" }
26+
litellm = { git = "https://github.com/otjamin/litellm", tag = "v1.72.6.rc.1" }
2727

2828
[tool.uv.workspace]
2929
members = ["agents/*"]

0 commit comments

Comments
 (0)