Blame Raw
· · · 66 lines (2.3 KB)
0 contributors
1import fetch from 'node-fetch';
2import express from 'express';
3
4import { readSecret, SECRET_KEYS } from './secrets.js';
5
6export const router = express.Router();
7
8router.post('/caption-image', async (request, response) => {
9 try {
10 const mimeType = request.body.image.split(';')[0].split(':')[1];
11 const base64Data = request.body.image.split(',')[1];
12 const baseUrl = request.body.reverse_proxy ? request.body.reverse_proxy : 'https://api.anthropic.com/v1';
13 const url = `${baseUrl}/messages`;
14 const body = {
15 model: request.body.model,
16 messages: [
17 {
18 'role': 'user', 'content': [
19 {
20 'type': 'image',
21 'source': {
22 'type': 'base64',
23 'media_type': mimeType,
24 'data': base64Data,
25 },
26 },
27 { 'type': 'text', 'text': request.body.prompt },
28 ],
29 },
30 ],
31 max_tokens: 4096,
32 };
33
34 console.debug('Multimodal captioning request', body);
35
36 const result = await fetch(url, {
37 body: JSON.stringify(body),
38 method: 'POST',
39 headers: {
40 'Content-Type': 'application/json',
41 'anthropic-version': '2023-06-01',
42 'x-api-key': request.body.reverse_proxy ? request.body.proxy_password : readSecret(request.user.directories, SECRET_KEYS.CLAUDE),
43 },
44 });
45
46 if (!result.ok) {
47 const text = await result.text();
48 console.warn(`Claude API returned error: ${result.status} ${result.statusText}`, text);
49 return response.status(result.status).send({ error: true });
50 }
51
52 /** @type {any} */
53 const generateResponseJson = await result.json();
54 const caption = generateResponseJson.content[0].text;
55 console.debug('Claude response:', generateResponseJson);
56
57 if (!caption) {
58 return response.status(500).send('No caption found');
59 }
60
61 return response.json({ caption });
62 } catch (error) {
63 console.error(error);
64 response.status(500).send('Internal server error');
65 }
66});