halbot 1993.2.23 → 1993.2.25
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +0 -6
- package/index.mjs +38 -46
- package/package.json +3 -3
- package/skills/60_prepare.mjs +18 -4
package/README.md
CHANGED
|
@@ -91,12 +91,6 @@ All supported configuration fields:
|
|
|
91
91
|
// OPTIONAL, integer, default: 1.
|
|
92
92
|
"chatGptPriority": "[[Custom ChatGPT Priority]]",
|
|
93
93
|
|
|
94
|
-
// Set some of these fields if you need to use custom ChatGPT API.
|
|
95
|
-
// OPTIONAL, string.
|
|
96
|
-
"chatGptApiKey": "[[Custom ChatGPT API Key]]",
|
|
97
|
-
// OPTIONAL, string.
|
|
98
|
-
"chatGptEndpoint": "[[Custom ChatGPT API endpoint]]",
|
|
99
|
-
|
|
100
94
|
// Set some of these fields if you need Anthropic's Claude features.
|
|
101
95
|
// OPTIONAL, string.
|
|
102
96
|
"claudeApiKey": "[[Anthropic API Key]]",
|
package/index.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { alan, bot, image, shot, speech, utilitas
|
|
1
|
+
import { alan, bot, image, shot, speech, utilitas } from 'utilitas';
|
|
2
2
|
import { parse } from 'csv-parse/sync';
|
|
3
3
|
|
|
4
4
|
await utilitas.locate(utilitas.__(import.meta.url, 'package.json'));
|
|
@@ -29,40 +29,51 @@ const fetchPrompts = async () => {
|
|
|
29
29
|
|
|
30
30
|
const init = async (options) => {
|
|
31
31
|
assert(options?.telegramToken, 'Telegram Bot API Token is required.');
|
|
32
|
-
const [pkg, ai, _speech, speechOptions, engines]
|
|
33
|
-
= [await utilitas.which(), {}, {}, { tts: true, stt: true }, {}];
|
|
32
|
+
const [pkg, ai, _speech, speechOptions, engines, vision]
|
|
33
|
+
= [await utilitas.which(), {}, {}, { tts: true, stt: true }, {}, {}];
|
|
34
34
|
const info = bot.lines([
|
|
35
35
|
`[${bot.EMOJI_BOT} ${pkg.title}](${pkg.homepage})`, pkg.description
|
|
36
36
|
]);
|
|
37
37
|
let embedding;
|
|
38
38
|
// init ai engines
|
|
39
|
-
if
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
39
|
+
// use AI vision, AI stt if ChatGPT or Gemini is enabled
|
|
40
|
+
if (options?.openaiApiKey || options?.googleApiKey) {
|
|
41
|
+
vision.read = alan.distillFile;
|
|
42
|
+
vision.see = alan.distillFile;
|
|
43
|
+
_speech.stt = alan.distillFile;
|
|
44
|
+
}
|
|
45
|
+
// use openai embedding, dall-e, tts if openai is enabled
|
|
46
|
+
if (options?.openaiApiKey) {
|
|
47
|
+
const apiKey = { apiKey: options.openaiApiKey };
|
|
48
|
+
await alan.init({ provider: 'OPENAI', ...apiKey, ...options || {} });
|
|
45
49
|
ai['ChatGPT'] = {
|
|
46
50
|
engine: 'CHATGPT', priority: options?.chatGptPriority || 0,
|
|
47
|
-
};
|
|
48
|
-
engines['CHATGPT'] = {
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
};
|
|
51
|
+
}; // only support custom model while prompting:
|
|
52
|
+
engines['CHATGPT'] = { model: options?.chatGptModel, };
|
|
53
|
+
embedding = alan.createOpenAIEmbedding;
|
|
54
|
+
await image.init(apiKey);
|
|
55
|
+
await speech.init({ ...apiKey, provider: 'OPENAI', ...speechOptions });
|
|
56
|
+
_speech.tts = speech.tts;
|
|
52
57
|
}
|
|
58
|
+
// use gemini embedding if gemini is enabled and chatgpt is not enabled
|
|
59
|
+
// use google tts if google api key is ready
|
|
53
60
|
if (options?.googleApiKey) {
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
...options || {},
|
|
61
|
+
const apiKey = { apiKey: options.googleApiKey };
|
|
62
|
+
await alan.init({ // only support custom model while initiating:
|
|
63
|
+
provider: 'GEMINI', ...apiKey,
|
|
64
|
+
model: options?.geminiModel, ...options || {},
|
|
58
65
|
});
|
|
59
66
|
ai['Gemini'] = {
|
|
60
67
|
engine: 'GEMINI', priority: options?.geminiPriority || 1,
|
|
61
|
-
};
|
|
62
|
-
engines['GEMINI'] = {
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
68
|
+
}; // save for reference not for prompting:
|
|
69
|
+
engines['GEMINI'] = { model: options?.geminiModel };
|
|
70
|
+
embedding || (embedding = alan.createGeminiEmbedding);
|
|
71
|
+
if (!_speech.tts) {
|
|
72
|
+
await speech.init({
|
|
73
|
+
...apiKey, provider: 'GOOGLE', ...speechOptions,
|
|
74
|
+
});
|
|
75
|
+
_speech.tts = speech.tts;
|
|
76
|
+
}
|
|
66
77
|
}
|
|
67
78
|
if (options?.claudeApiKey) {
|
|
68
79
|
await alan.init({
|
|
@@ -71,11 +82,8 @@ const init = async (options) => {
|
|
|
71
82
|
});
|
|
72
83
|
ai['Claude'] = {
|
|
73
84
|
engine: 'CLAUDE', priority: options?.claudePriority || 2,
|
|
74
|
-
};
|
|
75
|
-
engines['CLAUDE'] = {
|
|
76
|
-
// only support custom model while prompting
|
|
77
|
-
model: options?.claudeModel,
|
|
78
|
-
};
|
|
85
|
+
}; // only support custom model while prompting:
|
|
86
|
+
engines['CLAUDE'] = { model: options?.claudeModel };
|
|
79
87
|
}
|
|
80
88
|
if (options?.ollamaEnabled || options?.ollamaEndpoint) {
|
|
81
89
|
await alan.init({
|
|
@@ -92,27 +100,12 @@ const init = async (options) => {
|
|
|
92
100
|
assert(utilitas.countKeys(ai), 'No AI provider is configured.');
|
|
93
101
|
await alan.initChat({ engines, sessions: options?.storage });
|
|
94
102
|
for (const i in ai) { ai[i].model = engines[ai[i].engine].model; }
|
|
95
|
-
//
|
|
96
|
-
if (options?.openaiApiKey) {
|
|
97
|
-
const apiKey = { apiKey: options.openaiApiKey };
|
|
98
|
-
await image.init(apiKey);
|
|
99
|
-
await speech.init({ ...apiKey, provider: 'OPENAI', ...speechOptions });
|
|
100
|
-
embedding = alan.createOpenAIEmbedding;
|
|
101
|
-
} else if (options?.googleApiKey) {
|
|
102
|
-
const apiKey = { apiKey: options.googleApiKey };
|
|
103
|
-
await speech.init({ ...apiKey, provider: 'GOOGLE', ...speechOptions });
|
|
104
|
-
embedding = alan.createGeminiEmbedding;
|
|
105
|
-
}
|
|
106
|
-
// init vision / audio engine
|
|
103
|
+
// config multimodal engines
|
|
107
104
|
const supportedMimeTypes = new Set(Object.values(engines).map(
|
|
108
105
|
x => alan.MODELS[x.model]
|
|
109
106
|
).map(x => [
|
|
110
107
|
...x.supportedMimeTypes || [], ...x.supportedAudioTypes || [],
|
|
111
108
|
]).flat().map(x => x.toLowerCase()));
|
|
112
|
-
if (options?.googleApiKey) {
|
|
113
|
-
const apiKey = { apiKey: options.googleApiKey };
|
|
114
|
-
await vision.init(apiKey);
|
|
115
|
-
}
|
|
116
109
|
// init bot
|
|
117
110
|
const _bot = await bot.init({
|
|
118
111
|
args: options?.args,
|
|
@@ -131,8 +124,7 @@ const init = async (options) => {
|
|
|
131
124
|
botProvider: 'telegram',
|
|
132
125
|
session: options?.storage,
|
|
133
126
|
skillPath: options?.skillPath || skillPath,
|
|
134
|
-
speech:
|
|
135
|
-
vision: options?.googleApiKey && vision,
|
|
127
|
+
speech: _speech, vision,
|
|
136
128
|
});
|
|
137
129
|
_bot._.ai = ai; // Should be an array of a map of AIs.
|
|
138
130
|
_bot._.lang = options?.lang || 'English';
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "halbot",
|
|
3
3
|
"description": "Just another `ChatGPT` / `Gemini` / `Ollama` Telegram bob, which is simple design, easy to use, extendable and fun.",
|
|
4
|
-
"version": "1993.2.
|
|
4
|
+
"version": "1993.2.25",
|
|
5
5
|
"private": false,
|
|
6
6
|
"homepage": "https://github.com/Leask/halbot",
|
|
7
7
|
"type": "module",
|
|
@@ -40,7 +40,7 @@
|
|
|
40
40
|
"csv-parse": "^5.6.0",
|
|
41
41
|
"fluent-ffmpeg": "^2.1.3",
|
|
42
42
|
"ioredis": "^5.4.2",
|
|
43
|
-
"js-tiktoken": "^1.0.
|
|
43
|
+
"js-tiktoken": "^1.0.17",
|
|
44
44
|
"jsdom": "^26.0.0",
|
|
45
45
|
"lorem-ipsum": "^2.0.8",
|
|
46
46
|
"mime": "^4.0.6",
|
|
@@ -52,7 +52,7 @@
|
|
|
52
52
|
"pgvector": "^0.2.0",
|
|
53
53
|
"telegraf": "^4.16.3",
|
|
54
54
|
"tesseract.js": "^6.0.0",
|
|
55
|
-
"utilitas": "^1998.2.
|
|
55
|
+
"utilitas": "^1998.2.13",
|
|
56
56
|
"youtube-transcript": "^1.2.1"
|
|
57
57
|
}
|
|
58
58
|
}
|
package/skills/60_prepare.mjs
CHANGED
|
@@ -1,5 +1,21 @@
|
|
|
1
1
|
import { alan, bot, utilitas } from 'utilitas';
|
|
2
2
|
|
|
3
|
+
const checkUnsupportedMimeType = async ctx => {
|
|
4
|
+
ctx.carry.attachments = [];
|
|
5
|
+
for (const x of ctx.collected.filter(x => x.type === 'PROMPT')) {
|
|
6
|
+
let notSupported = false;
|
|
7
|
+
ctx.selectedAi.map(y => {
|
|
8
|
+
if (![
|
|
9
|
+
...alan.MODELS[ctx._.ai[y].model]?.supportedMimeTypes || [],
|
|
10
|
+
...alan.MODELS[ctx._.ai[y].model]?.supportedAudioTypes || [],
|
|
11
|
+
].includes(y?.content?.mime_type)) { notSupported = true; }
|
|
12
|
+
});
|
|
13
|
+
notSupported ? await x.content.analyze() : ctx.carry.attachments.push({
|
|
14
|
+
...x.content, analyze: undefined,
|
|
15
|
+
});
|
|
16
|
+
}
|
|
17
|
+
};
|
|
18
|
+
|
|
3
19
|
const action = async (ctx, next) => {
|
|
4
20
|
// avatar
|
|
5
21
|
if (ctx.result) {
|
|
@@ -16,9 +32,7 @@ const action = async (ctx, next) => {
|
|
|
16
32
|
ctx.avatar = '😸';
|
|
17
33
|
}
|
|
18
34
|
// prompt
|
|
19
|
-
|
|
20
|
-
x => x.type === 'PROMPT'
|
|
21
|
-
).map(x => x.content);
|
|
35
|
+
await checkUnsupportedMimeType(ctx);
|
|
22
36
|
const maxInputTokens = alan.getMaxChatPromptLimit()
|
|
23
37
|
- alan.ATTACHMENT_TOKEN_COST * ctx.carry.attachments.length;
|
|
24
38
|
const additionInfo = ctx.collected.filter(
|
|
@@ -28,7 +42,7 @@ const action = async (ctx, next) => {
|
|
|
28
42
|
while (await alan.countTokens(
|
|
29
43
|
`${ctx.prompt}${additionInfo?.[0] || ''}`
|
|
30
44
|
) < maxInputTokens && additionInfo.length) {
|
|
31
|
-
ctx.prompt +=
|
|
45
|
+
ctx.prompt += `${additionInfo.shift()} `;
|
|
32
46
|
}
|
|
33
47
|
ctx.prompt = utilitas.trim(ctx.prompt);
|
|
34
48
|
additionInfo.filter(x => x).length && (ctx.prompt += '...');
|