@zodic/shared 0.0.426 → 0.0.427
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.
|
@@ -6,53 +6,81 @@ import { AppContext } from '../base';
|
|
|
6
6
|
export class ImageDescriberService {
|
|
7
7
|
constructor(@inject(AppContext) private context: AppContext) {}
|
|
8
8
|
|
|
9
|
-
// Helper function to add a delay
|
|
10
9
|
private delay(ms: number): Promise<void> {
|
|
11
10
|
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
12
11
|
}
|
|
13
12
|
|
|
13
|
+
private async fetchImageAsBase64(imageUrl: string): Promise<string> {
|
|
14
|
+
const response = await fetch(imageUrl);
|
|
15
|
+
if (!response.ok) {
|
|
16
|
+
throw new Error(`Failed to fetch image: ${response.status} ${response.statusText}`);
|
|
17
|
+
}
|
|
18
|
+
const contentType = response.headers.get('Content-Type') || 'image/jpeg';
|
|
19
|
+
const buffer = await response.arrayBuffer();
|
|
20
|
+
const base64 = btoa(
|
|
21
|
+
String.fromCharCode(...new Uint8Array(buffer))
|
|
22
|
+
);
|
|
23
|
+
return `data:${contentType};base64,${base64}`;
|
|
24
|
+
}
|
|
25
|
+
|
|
14
26
|
async describeImage({ imageUrl }: { imageUrl: string }): Promise<string> {
|
|
15
27
|
console.log('ImageDescriber imageUrl ->', imageUrl);
|
|
16
28
|
|
|
17
29
|
const MAX_RETRIES = 3;
|
|
18
30
|
const RETRY_DELAY_MS = 1000;
|
|
19
31
|
|
|
32
|
+
const env = this.context.env;
|
|
33
|
+
if (!env.AI) {
|
|
34
|
+
throw new Error('AI binding is not available in the environment.');
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
const dataUri = await this.fetchImageAsBase64(imageUrl);
|
|
38
|
+
|
|
20
39
|
let lastError: Error | null = null;
|
|
21
40
|
|
|
22
41
|
for (let attempt = 1; attempt <= MAX_RETRIES; attempt++) {
|
|
23
42
|
console.log(`Attempting to describe image (Attempt ${attempt}/${MAX_RETRIES})`);
|
|
24
43
|
|
|
25
44
|
try {
|
|
26
|
-
const response = await
|
|
27
|
-
|
|
28
|
-
{
|
|
29
|
-
role: 'user',
|
|
30
|
-
content: [
|
|
31
|
-
{
|
|
32
|
-
type: 'text',
|
|
33
|
-
text: 'Describe the following traits of the person in the picture:\n- Hair color, size and style\n- Skin color\n\nReturn the result in the following format:\n\nHair: hair description\nSkin: skin description',
|
|
34
|
-
},
|
|
35
|
-
{
|
|
36
|
-
type: 'image_url',
|
|
37
|
-
image_url: {
|
|
38
|
-
url: imageUrl,
|
|
39
|
-
},
|
|
40
|
-
},
|
|
41
|
-
],
|
|
42
|
-
},
|
|
43
|
-
],
|
|
45
|
+
const response = await env.AI.run(
|
|
46
|
+
'@cf/meta/llama-3.2-11b-vision-instruct' as any,
|
|
44
47
|
{
|
|
45
|
-
|
|
46
|
-
|
|
48
|
+
messages: [
|
|
49
|
+
{
|
|
50
|
+
role: 'user',
|
|
51
|
+
content: [
|
|
52
|
+
{
|
|
53
|
+
type: 'text',
|
|
54
|
+
text: `You are analyzing a photo of a person. Describe ONLY these physical traits concisely and accurately:
|
|
55
|
+
|
|
56
|
+
1. HAIR: color (e.g. black, dark brown, light brown, blonde, red, gray), length (short, medium, long), and style (straight, wavy, curly, coiled, braided, shaved)
|
|
57
|
+
2. SKIN: tone (e.g. very light/pale, light, medium/olive, tan, brown, dark brown, deep/dark)
|
|
58
|
+
|
|
59
|
+
Respond in EXACTLY this format, nothing else:
|
|
60
|
+
Hair: [color], [length], [style]
|
|
61
|
+
Skin: [tone]`,
|
|
62
|
+
},
|
|
63
|
+
{
|
|
64
|
+
type: 'image_url',
|
|
65
|
+
image_url: {
|
|
66
|
+
url: dataUri,
|
|
67
|
+
},
|
|
68
|
+
},
|
|
69
|
+
],
|
|
70
|
+
},
|
|
71
|
+
],
|
|
72
|
+
max_tokens: 100,
|
|
73
|
+
temperature: 0.2,
|
|
47
74
|
}
|
|
48
75
|
);
|
|
49
76
|
|
|
50
|
-
|
|
51
|
-
|
|
77
|
+
const result = (response as any)?.response;
|
|
78
|
+
if (!result) {
|
|
79
|
+
throw new Error('No response received from Workers AI');
|
|
52
80
|
}
|
|
53
81
|
|
|
54
|
-
console.log('Successfully described image with
|
|
55
|
-
return
|
|
82
|
+
console.log('Successfully described image with Workers AI (Llama Vision):', result);
|
|
83
|
+
return result;
|
|
56
84
|
} catch (error) {
|
|
57
85
|
lastError = error as Error;
|
|
58
86
|
console.error(`Error describing image (attempt ${attempt}):`, error);
|