Message Attachment Image Recognition (#118)

* Add: Image recognition

* Fix: Non-Attachment Query

* Update: version increment

* Remove: Debugging logs from buffer file

* Add: comments for bufferHandler
This commit is contained in:
Kevin Dang
2024-09-18 20:28:23 -07:00
committed by GitHub
parent 36a0cd309b
commit e3b0c9abe4
8 changed files with 74 additions and 9 deletions

View File

@@ -7,7 +7,7 @@ services:
build: ./ # find docker file in designated path build: ./ # find docker file in designated path
container_name: discord container_name: discord
restart: always # rebuild container always restart: always # rebuild container always
image: kevinthedang/discord-ollama:0.5.11 image: kevinthedang/discord-ollama:0.6.0
environment: environment:
CLIENT_TOKEN: ${CLIENT_TOKEN} CLIENT_TOKEN: ${CLIENT_TOKEN}
MODEL: ${MODEL} MODEL: ${MODEL}

4
package-lock.json generated
View File

@@ -1,12 +1,12 @@
{ {
"name": "discord-ollama", "name": "discord-ollama",
"version": "0.5.11", "version": "0.6.0",
"lockfileVersion": 3, "lockfileVersion": 3,
"requires": true, "requires": true,
"packages": { "packages": {
"": { "": {
"name": "discord-ollama", "name": "discord-ollama",
"version": "0.5.11", "version": "0.6.0",
"license": "ISC", "license": "ISC",
"dependencies": { "dependencies": {
"discord.js": "^14.15.3", "discord.js": "^14.15.3",

View File

@@ -1,6 +1,6 @@
{ {
"name": "discord-ollama", "name": "discord-ollama",
"version": "0.5.11", "version": "0.6.0",
"description": "Ollama Integration into discord", "description": "Ollama Integration into discord",
"main": "build/index.js", "main": "build/index.js",
"exports": "./build/index.js", "exports": "./build/index.js",

View File

@@ -45,5 +45,6 @@ await client.login(Keys.clientToken)
// queue up bots name // queue up bots name
messageHistory.enqueue({ messageHistory.enqueue({
role: 'assistant', role: 'assistant',
content: `My name is ${client.user?.username}` content: `My name is ${client.user?.username}`,
images: []
}) })

View File

@@ -1,5 +1,5 @@
import { embedMessage, event, Events, normalMessage, UserMessage } from '../utils/index.js' import { embedMessage, event, Events, normalMessage, UserMessage } from '../utils/index.js'
import { getChannelInfo, getServerConfig, getUserConfig, openChannelInfo, openConfig, ServerConfig, UserConfig } from '../utils/index.js' import { getChannelInfo, getServerConfig, getUserConfig, openChannelInfo, openConfig, UserConfig, getAttachmentData } from '../utils/index.js'
import { clean } from '../utils/mentionClean.js' import { clean } from '../utils/mentionClean.js'
import { TextChannel } from 'discord.js' import { TextChannel } from 'discord.js'
@@ -102,6 +102,9 @@ export default event(Events.MessageCreate, async ({ log, msgHist, tokens, ollama
// response string for ollama to put its response // response string for ollama to put its response
let response: string let response: string
// get message attachment if exists
const messageAttachment: string[] = await getAttachmentData(message.attachments.first())
// set up new queue // set up new queue
msgHist.setQueue(chatMessages) msgHist.setQueue(chatMessages)
@@ -111,7 +114,8 @@ export default event(Events.MessageCreate, async ({ log, msgHist, tokens, ollama
// push user response before ollama query // push user response before ollama query
msgHist.enqueue({ msgHist.enqueue({
role: 'user', role: 'user',
content: clean(message.content) content: clean(message.content),
images: messageAttachment || []
}) })
// undefined or false, use normal, otherwise use embed // undefined or false, use normal, otherwise use embed
@@ -129,7 +133,8 @@ export default event(Events.MessageCreate, async ({ log, msgHist, tokens, ollama
// successful query, save it in context history // successful query, save it in context history
msgHist.enqueue({ msgHist.enqueue({
role: 'assistant', role: 'assistant',
content: response content: response,
images: messageAttachment || []
}) })
// only update the json on success // only update the json on success

View File

@@ -38,7 +38,8 @@ export type ChatParams = {
*/ */
export type UserMessage = { export type UserMessage = {
role: string, role: string,
content: string content: string,
images: string[] // May or may not have images in message
} }
// Event properties // Event properties

View File

@@ -0,0 +1,57 @@
import { Attachment } from "discord.js"
/**
* Method to convert a Discord attachment url to an array buffer
*
* @param url Discord Attachment Url
* @returns array buffer from Attachment Url
*/
async function getAttachmentBuffer(url: string): Promise<ArrayBuffer> {
// Get the data from the image
const response = await fetch(url)
// Validate the image came in fine
if (!response.ok)
throw new Error('Failed to fetch the attachment.')
// Return image as Buffer
return await response.arrayBuffer()
}
/**
* Method to convert an array buffer to a Base64 String
*
* @param buffer Array Buffer from attachment
* @returns converted Base64 string
*/
function arrayBufferToBase64(buffer: ArrayBuffer): string {
// Converting to Uint8Array
const uint8Array = new Uint8Array(buffer)
let binary = ''
const len = uint8Array.byteLength;
for (let i = 0; i < len; i++) {
binary += String.fromCharCode(uint8Array[i])
}
// Return as Base64
return Buffer.from(binary, 'binary').toString('base64')
}
/**
* Method to retrieve the Base64 Array of provided Message Attachment
*
* @param attachment Message Attachment from Discord
* @returns Base64 string array
*/
export async function getAttachmentData(attachment: Attachment | undefined): Promise<string[]> {
const url: string = attachment !== undefined ? attachment.url : "Missing Url"
// case of no attachment
if (url === "Missing Url")
return []
// Convert data to base64
const buffer = await getAttachmentBuffer(url)
const base64String = arrayBufferToBase64(buffer)
return [base64String]
}

View File

@@ -10,3 +10,4 @@ export * from './configInterfaces.js'
export * from './handlers/chatHistoryHandler.js' export * from './handlers/chatHistoryHandler.js'
export * from './handlers/configHandler.js' export * from './handlers/configHandler.js'
export * from './handlers/streamHandler.js' export * from './handlers/streamHandler.js'
export * from './handlers/bufferHandler.js'