Skip to content

Commit 0582d84

Browse files
committed
use bot.streamReply
1 parent 1946a29 commit 0582d84

2 files changed

Lines changed: 58 additions & 20 deletions

File tree

packages/main/src/telegram_execution_context.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -188,7 +188,6 @@ export default class TelegramExecutionContext {
188188
return await this.api.sendMessageDraft(this.bot.api.toString(), {
189189
...options,
190190
chat_id: this.getChatId(),
191-
reply_to_message_id: this.getMessageId(),
192191
text: message,
193192
parse_mode,
194193
});

packages/worker/src/index.ts

Lines changed: 58 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -34,17 +34,68 @@ function wrapPromise<T>(func: promiseFunc<T>, time = 1000) {
3434
*/
3535
async function markdownToHtml(s: string): Promise<string> {
3636
marked.setOptions(marked.getDefaults());
37-
const parsed = await marked.parse(s) as string | { toString(): string };
37+
const parsed = (await marked.parse(s)) as string | { toString(): string };
3838
const parsedString = typeof parsed === 'string' ? parsed : parsed.toString();
3939
const tagsToRemove = ['p', 'ol', 'ul', 'li', 'h1', 'h2', 'h3'];
4040
const tagPattern = new RegExp(tagsToRemove.map((tag) => `<${tag}>|</${tag}>`).join('|'), 'g');
4141
return parsedString.replace(tagPattern, '');
4242
}
4343

44+
/**
45+
* Stream AI response and send periodic updates via bot.streamReply
46+
* @param bot - the telegram execution context
47+
* @param env - the environment
48+
* @param model - the AI model to use
49+
* @param messages - the messages to send
50+
* @returns the full response string
51+
*/
52+
async function streamAiResponse(
53+
bot: TelegramExecutionContext,
54+
env: Environment,
55+
model: string,
56+
messages: { role: string; content: string }[],
57+
): Promise<string> {
58+
// @ts-expect-error broken bindings
59+
const response = (await env.AI.run(model, {
60+
messages,
61+
stream: true,
62+
})) as ReadableStream;
63+
64+
const reader = response.getReader();
65+
const decoder = new TextDecoder();
66+
let fullResponse = '';
67+
let lastUpdate = Date.now();
68+
69+
while (true) {
70+
const { done, value } = await reader.read();
71+
if (done) break;
72+
73+
const chunk = decoder.decode(value);
74+
const lines = chunk.split('\n');
75+
76+
for (const line of lines) {
77+
if (line.startsWith('data: ') && line !== 'data: [DONE]') {
78+
try {
79+
const data = JSON.parse(line.slice(6)) as { response: string };
80+
fullResponse += data.response;
81+
82+
if (Date.now() - lastUpdate > 5000) {
83+
await bot.streamReply(await markdownToHtml(fullResponse), 'HTML');
84+
lastUpdate = Date.now();
85+
}
86+
} catch (e) {
87+
console.error('Error parsing AI stream:', e);
88+
}
89+
}
90+
}
91+
}
92+
return fullResponse;
93+
}
94+
4495
// Constants for system prompts
4596
const SYSTEM_PROMPTS = {
4697
TUX_ROBOT: 'You are a friendly assistant named TuxRobot. Use lots of emojis in your responses.',
47-
SEAN: 'You are a friendly person named Sean. Sometimes just acknowledge messages with okay. You are working on coding a cool telegram bot. You are 26 years old and from Toronto, Canada.',
98+
SEAN: 'You are a friendly person named Sean. Sometimes just acknowledge messages with okay. You are working on coding a cool telegram bot.',
4899
};
49100

50101
// AI model constants
@@ -122,7 +173,7 @@ export default {
122173
.on(':message', async (bot: TelegramExecutionContext) => {
123174
switch (bot.update_type) {
124175
case 'message': {
125-
await bot.sendTyping();
176+
// await bot.sendTyping();
126177
const prompt = bot.update.message?.text?.toString() ?? '';
127178

128179
const { results } = await env.DB.prepare('SELECT * FROM Messages WHERE userId=?')
@@ -138,25 +189,13 @@ export default {
138189

139190
try {
140191
console.log('Processing text message:', prompt);
141-
// @ts-expect-error broken bindings
142-
const response = await env.AI.run(AI_MODELS.LLAMA, { messages });
192+
const response = await streamAiResponse(bot, env, AI_MODELS.LLAMA, messages);
143193

144-
if ('response' in response && response.response) {
145-
await bot.reply(
146-
await markdownToHtml(
147-
typeof response.response === 'string'
148-
? response.response
149-
: JSON.stringify(response.response)
150-
),
151-
'HTML'
152-
);
194+
if (response) {
195+
await bot.reply(await markdownToHtml(response), 'HTML');
153196

154197
await env.DB.prepare('INSERT INTO Messages (id, userId, content) VALUES (?, ?, ?)')
155-
.bind(
156-
crypto.randomUUID(),
157-
bot.update.message?.from.id,
158-
`'[INST] ${prompt} [/INST] \n ${typeof response.response === 'string' ? response.response : JSON.stringify(response.response)}'`
159-
)
198+
.bind(crypto.randomUUID(), bot.update.message?.from.id, `'[INST] ${prompt} [/INST] \n ${response}'`)
160199
.run();
161200
}
162201
} catch (e) {

0 commit comments

Comments
 (0)