先日投稿した「Dify APIを使ってみる」で紹介したNodeJSを使ったアプリケーションの続きです。
まずは実行中の様子。VS Codium上でThunderClientという拡張機能からHTTPリクエストを送信しています。
こんな結果が帰ってきます。生成された文章がMarkdown形式だったので、VS CodiumのMarkdownプレビュー画面で表示しています。
以下、ソースコードです。
const axios = require('axios')
const http = require('http')
require('dotenv').config()
const API_KEY = process.env.API_KEY
const API_URL = process.env.API_URL
const PORT = process.env.PORT
const messages = [
{ "role": "user", "content": "こんにちは!" },
{ "role": "assistant", "content": "こんにちは! 何についてお話しましょうか?" },
{ "role": "user", "content": "日本語で会話しましょう。" }
];
const default_messages = [
{ "role": "user", "content": "こんにちは!" },
{ "role": "assistant", "content": "こんにちは! 何についてお話しましょうか?" },
{ "role": "user", "content": "日本語で会話しましょう。" }
]
const conversation = { messages }
const headers = {
'Authorization': `Bearer ${API_KEY}`,
'Content-Type': 'application/json',
};
const data = {
"response_mode": "blocking",
"conversation_id": "",
"user": "kazuo.tsubaki@zikuu.space",
"files": [
{
"type": "image",
"transfer_method": "remote_url",
"url": "https://cloud.dify.ai/logo/logo-site.png"
}
]
};
const inference_call = async(prompt, id, res) => {
data.query = prompt;
if(id) {
data.conversation_id = id;
} else {
data.conversation_id = "";
conversation.messages = default_messages;
}
data.inputs = conversation.messages;
console.log('API:', data);
await axios.post(API_URL, data, { headers })
.then(response => {
const resp = response.data;
const assistantMessage = resp.answer;
console.log('アシスタント:', assistantMessage);
conversation.id = resp.conversation_id
// 過去のメッセージ履歴にアシスタントの応答を追加
conversation.messages.push({ "role": "user", "content": prompt });
conversation.messages.push({ "role": "assistant", "content": assistantMessage });
console.log(conversation)
// 結果を返す
res.statusCode = 200;
res.setHeader('Content-type', 'application/json');
res.end(JSON.stringify({id: conversation.id, answer: assistantMessage}, null, 2));
})
.catch(error => {
console.error('エラーが発生しました:', error);
});
}
const server = http.createServer((req, res) => {
const { method, url } = req;
if (method === 'POST' && url === '/chat') {
let body = '';
req.on('data', (chunk) => {
body += chunk;
});
req.on('end', () => {
try {
console.log('Received data: ', body);
const json = JSON.parse(body);
console.log(json)
const prompt = json.prompt;
const id = json.id;
inference_call(prompt, id, res).then(() => { }, (error) => {
res.statusCode = 400;
res.setHeader('Content-Type', 'text/plain');
res.end(`エラーが発生しました: ${error}`);
});
} catch (error) {
res.statusCode = 400;
res.setHeader('Content-Type', 'text/plain');
res.end(`エラーが発生しました: ${error}`);
}
});
} else {
res.statusCode = 404;
res.setHeader('Content-Type', 'text/plain');
res.end('Not Found');
}
})
server.listen(PORT, '127.0.0.1', () => {
console.log(`Server running at http://127.0.0.1:${PORT}/`);
})
使用した大規模言語モデルはGemma 2の9B。それをOllamaで動かし、Difyでチャットボットとして利用しているものです。
モノづくり塾のアプリケーションサーバーにはディスクリートGPUが搭載されていないので、まだこのような生成AIアプリケーションを運用できていませんが、いずれサーバーにGPUを載せて、Dockerでこのアプリケーションをデプロイし、ZIKUUコミュニティーのDiscordから呼び出せるようにしようと思っています。