/
server.js
209 lines (164 loc) · 5.22 KB
/
server.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
import 'dotenv/config'
import fs from "fs";
import bodyParser from 'body-parser';
import express from 'express';
import nunjucks from 'nunjucks';
import Anthropic from '@anthropic-ai/sdk';
import fetch from 'node-fetch';
var app = express();
// parse application/x-www-form-urlencoded
app.use(bodyParser.urlencoded({ extended: false }))
// parse application/json
app.use(bodyParser.json())
import path from 'path';
import { fileURLToPath } from 'url';
const __filename = fileURLToPath(import.meta.url); // get the resolved path to the file
const __dirname = path.dirname(__filename); // get the name of the directory
import extractFormQuestions from './data/extract-form-questions.json' assert { type: 'json' };
// get API Key from environment variable ANTHROPIC_API_KEY
const anthropic = new Anthropic();
app.use('/assets', express.static(path.join(__dirname, '/node_modules/govuk-frontend/dist/govuk/assets')))
nunjucks.configure([
'app/views',
'node_modules/govuk-frontend/dist/'
],
{
autoescape: true,
express: app,
noCache: true
})
app.set('view engine', 'html')
app.use(express.json());
app.use(express.static('public'));
// CALL CLAUDE
app.post('/sendToClaude', async (req, res) => {
// Encode the image data into base64
const image_url = req.body.imageURL;
const image_media_type = "image/jpeg"
const image_array_buffer = await ((await fetch(image_url)).arrayBuffer());
const image_data = Buffer.from(image_array_buffer).toString('base64');
// Create a HTML wrapper for the JSON result to go in
const jsonWrapper = (content) => `
{% extends "json.njk" %}
{% block result %}${content}{% endblock %}
`;
// Create a HTML wrapper for the List result to go in
const listWrapper = (content) => `
{% extends "list.njk" %}
{% set resultJSON = ${content} %}
`;
// Create a HTML wrapper for the Form result to go in
const formWrapper = (content) => `
{% extends "form.njk" %}
{% set resultJSON = ${content} %}
`;
// Create the prompt to send with the image and the tool
const prompt = [
"Is this a form?",
"It's only a form if it contains form field boxes.",
"Hand drawn forms, questionnaires and surveys are all valid forms.",
"If it is a form, extract the questions from it using the extract_form_questions tool."
].join();
// Call Claude!
try {
const message = await anthropic.beta.tools.messages.create({
model: 'claude-3-opus-20240229', // The 2 smaller models generate API errors
temperature: 0.0, // Low temp keeps the results more consistent
max_tokens: 2048,
tools: [ extractFormQuestions ],
messages: [{
"role": "user",
"content": [
{
"type": "image",
"source": {
"type": "base64",
"media_type": image_media_type,
"data": image_data,
},
},
{
"type": "text",
"text": prompt
}
],
}]
});
console.log(message);
let result = message.content[1].input;
result.imageURL = image_url;
// Write the results into a 'results' folder
const now = `${Date.now()}`;
// Write the files
try {
fs.writeFileSync('app/data/' + now + '.json', JSON.stringify(result, null, 2));
} catch (err) {
console.error(err);
}
res.redirect('/results/' + now);
} catch(error) {
console.error('Error in Claude API call:', error);
return res.status(500).send('Error processing the request');
}
});
// THE WEB PAGES
const port = 3000;
/* Render query page */
app.get('/', (req, res) => {
res.render('index.html')
})
/* Render loading page */
app.get('/loading.html', (req, res) => {
res.render('loading.html')
})
// load form data
function loadFormData(formId){
try {
return JSON.parse(fs.readFileSync('./app/data/'+formId+'.json'))
} catch (err) {
console.error(err)
}
}
/* Render form pages */
app.get('/forms/:formId/:question', (req, res) => {
const formId = req.params.formId
const question = Number(req.params.question)
const formData = loadFormData(formId)
res.locals.formData = formData
res.locals.question = question
res.locals.formId = formId
res.render('form.njk');
})
/* Render check-answers pages */
app.get('/check-answers/:formId', (req, res) => {
const formId = req.params.formId
const formData = loadFormData(formId)
res.locals.formData = formData
res.locals.formId = formId
res.render('check-answers.njk')
})
/* Render list pages */
app.get('/lists/:formId', (req, res) => {
const formId = req.params.formId
const formData = loadFormData(formId)
res.locals.formData = formData
res.render('list.njk')
})
/* Render JSON pages */
app.get('/json/:formId', (req, res) => {
const formId = req.params.formId
let formData = loadFormData(formId)
formData = JSON.stringify(formData, null, 2);
res.locals.formData = formData
res.render('json.njk')
})
app.get('/results/:formId', (req, res) => {
const formId = req.params.formId
const formData = loadFormData(formId)
res.locals.formId = formId
res.locals.formData = formData
res.render('result')
})
app.listen(port, () => {
console.log('Server running at http://localhost:3000');
})