207 lines
6.5 KiB
JavaScript
207 lines
6.5 KiB
JavaScript
const { Webhook } = require('discord-webhook-node');
|
||
const readline = require("readline");
|
||
const { Ollama } = require("ollama");
|
||
const clc = require("cli-color");
|
||
const fs = require('fs');
|
||
|
||
const ollama = new Ollama({ host: "http://127.0.0.1:11434" });
|
||
const discordHook = new Webhook("https://discord.com/api/webhooks/1328616300544786444/oCwaJ1HQW_Hk0_BQB6lWfuLSikhGOzEJqaOr37MNb6lkICk0Bllk7izVPdmXHKm1JhAN");
|
||
|
||
const modelName = "qwen2.5:7b";
|
||
const sessionName = modelName.replace(/[.:]/g, "");//+ "_" + (Math.floor(new Date().getTime() / 1000)).toString();
|
||
|
||
const messageHistory = [];
|
||
|
||
function discordMessage(args) {
|
||
try {
|
||
discordHook.setUsername("@Nyamma");
|
||
discordHook.send(args.message.toString());
|
||
} catch (error) {
|
||
console.log(error);
|
||
}
|
||
return "Message sent successfully!";
|
||
}
|
||
|
||
function getRandomCharacter(args) {
|
||
return "Miku";
|
||
}
|
||
|
||
function getRandomQuote(args) {
|
||
return '"Cerber is cute pass it on." -twitch chat';
|
||
}
|
||
|
||
function googleSearch(args) {
|
||
setTimeout(() => {
|
||
googleResult(args.query);
|
||
}, 10000);
|
||
return `Starting google search for ${args.query}, please wait a few minutes`;
|
||
}
|
||
|
||
async function googleResult(query) {
|
||
const result = "hatsune miku";
|
||
|
||
messageHistory.push({ role: "tool", content: `googleSearch: ${result}` });
|
||
await getResponse();
|
||
}
|
||
|
||
const availableFunctions = {
|
||
sendMessage: discordMessage,
|
||
getRandomCharacter: getRandomCharacter,
|
||
getRandomQuote: getRandomQuote,
|
||
doGoogleSearch: googleSearch
|
||
}
|
||
|
||
const availableTools = [
|
||
{
|
||
type: 'function',
|
||
function: {
|
||
name: 'sendMessage',
|
||
description: 'Send a message via discord to @shironeko.',
|
||
parameters: {
|
||
type: 'object',
|
||
required: ['message'],
|
||
properties: {
|
||
message: { type: 'string', description: 'Message contents.' }
|
||
}
|
||
}
|
||
}
|
||
},
|
||
{
|
||
type: 'function',
|
||
function: {
|
||
name: 'getRandomCharacter',
|
||
description: 'Gets random anime characters from randomCharacter.org, max 1.',
|
||
parameters: {
|
||
type: 'object',
|
||
required: ['amount'],
|
||
properties: {
|
||
amount: { type: 'string', description: 'Amount of characters to generate.' }
|
||
}
|
||
}
|
||
}
|
||
},
|
||
{
|
||
type: 'function',
|
||
function: {
|
||
name: 'getRandomQuote',
|
||
description: 'Gets random quotes from randomQuotes.org, max 1.',
|
||
parameters: {
|
||
type: 'object',
|
||
required: ['amount'],
|
||
properties: {
|
||
amount: { type: 'string', description: 'Amount of quotes to get.' }
|
||
}
|
||
}
|
||
}
|
||
},
|
||
{
|
||
type: 'function',
|
||
function: {
|
||
name: 'doGoogleSearch',
|
||
description: 'Search in google for a query, this might take some undefined amount of time so, wait for a late response',
|
||
parameters: {
|
||
type: 'object',
|
||
required: ['query'],
|
||
properties: {
|
||
query: { type: 'string', description: 'Query to search for' }
|
||
}
|
||
}
|
||
}
|
||
}
|
||
]
|
||
|
||
|
||
async function getUserInput() {
|
||
return new Promise((resolve) => {
|
||
const rl = readline.createInterface({
|
||
input: process.stdin,
|
||
output: process.stdout
|
||
});
|
||
rl.question("User: ", (input) => {
|
||
rl.close();
|
||
resolve(input);
|
||
});
|
||
});
|
||
}
|
||
|
||
function saveSessionData(messages) {
|
||
const jsonData = JSON.stringify({ messageList: messages }, null, 2);
|
||
|
||
fs.writeFile(`sessions/${sessionName}.json`, jsonData, "utf8", (err) => {
|
||
if (err) {
|
||
console.error("Error writing to file:", err);
|
||
}
|
||
});
|
||
}
|
||
|
||
|
||
async function handleToolCall(toolCalls) {
|
||
for (const tool of toolCalls) {
|
||
const { name, arguments: args } = tool.function;
|
||
const functionToCall = availableFunctions[name];
|
||
|
||
if (!functionToCall) {
|
||
console.error(`Tool "${name}" not found.`);
|
||
messageHistory.push({ role: "tool", content: `Tool "${name}" not recognized.` });
|
||
continue;
|
||
}
|
||
|
||
try {
|
||
// Execute the tool function
|
||
console.log(`Calling function: ${name}`);
|
||
console.log(`Arguments:`, args);
|
||
|
||
const output = await functionToCall(args);
|
||
console.log(`Function output: ${output}`);
|
||
|
||
// Update message history with tool output
|
||
messageHistory.push({ role: "tool", content: `${name}: ${output}` });
|
||
|
||
} catch (error) {
|
||
console.error(`Error executing tool "${name}":`, error);
|
||
messageHistory.push({ role: "tool", content: `Error executing tool "${name}".` });
|
||
}
|
||
}
|
||
|
||
// Process follow-up responses from the model after all tool calls are executed
|
||
await getResponse();
|
||
}
|
||
|
||
async function getResponse() {
|
||
const response = await ollama.chat({
|
||
model: modelName,
|
||
messages: messageHistory,
|
||
tools: availableTools
|
||
});
|
||
messageHistory.push(response.message);
|
||
|
||
|
||
// Handle additional tool calls, if any
|
||
if (response.message.tool_calls) {
|
||
await handleToolCall(response.message.tool_calls);
|
||
} else {
|
||
console.log(clc.blueBright("Nyamma:"), response.message.content);
|
||
}
|
||
saveSessionData(messageHistory);
|
||
}
|
||
|
||
async function runModel() {
|
||
messageHistory.push({ role: "system", content: "You are Nyamma, a cheerful and cute anime character with a playful, cat-like personality. You often use adorable expressions like \"nya~\" and love making others smile. You’re kind-hearted, energetic, and always eager to help, but can also be a bit mischievous in a charming way. You speak in a light, bubbly tone and sometimes mix in cat-like sounds, especially when you're excited or curious." });
|
||
//while (true) {
|
||
try {
|
||
//const userMessage = await getUserInput();
|
||
|
||
//const userMessage = "please get a random character, a random quote, and then send both to discord";
|
||
const userMessage = "please search in google for cute blue hair character, and when you get the result send it to me via discord";
|
||
messageHistory.push({ role: "user", content: userMessage });
|
||
|
||
await getResponse();
|
||
} catch (error) {
|
||
console.error("An error occurred:", error);
|
||
}
|
||
//}
|
||
}
|
||
|
||
runModel().catch((error) => {
|
||
console.error("Critical error in the main loop:", error);
|
||
}); |