feat: allow passing array of sections instead of entire message

Philipp Burckhardt 2023-06-16 20:03:02 -04:00
rodzic 3cce379a2d
commit f887ea239e
Nie znaleziono w bazie danych klucza dla tego podpisu
ID klucza GPG: A2C3BCA4F31D1DDD
3 zmienionych plików z 46 dodań i 24 usunięć

Wyświetl plik

@ -57,17 +57,18 @@ export class HumanFeedbackMechanismTwilio<
message: string, message: string,
choices: HumanFeedbackUserActions[] choices: HumanFeedbackUserActions[]
): Promise<HumanFeedbackUserActions> { ): Promise<HumanFeedbackUserActions> {
message += '\n\n'
message += choices
.map(
(choice, idx) => `${idx} - ${HumanFeedbackUserActionMessages[choice]}`
)
.join('\n')
message += '\n\n'
message += 'Reply with the number of your choice.'
const response = await this._twilioClient.sendAndWaitForReply({ const response = await this._twilioClient.sendAndWaitForReply({
name: 'human-feedback-ask', name: 'human-feedback-ask',
text: message, text: [
message,
choices
.map(
(choice, idx) =>
`${idx} - ${HumanFeedbackUserActionMessages[choice]}`
)
.join('\n'),
'Reply with the number of your choice.'
],
timeoutMs: this._options.timeoutMs, timeoutMs: this._options.timeoutMs,
validate: (message) => { validate: (message) => {
const choice = parseInt(message.body) const choice = parseInt(message.body)
@ -87,10 +88,11 @@ export class HumanFeedbackMechanismTwilio<
const { body: selectedOutput } = const { body: selectedOutput } =
await this._twilioClient.sendAndWaitForReply({ await this._twilioClient.sendAndWaitForReply({
name: 'human-feedback-select', name: 'human-feedback-select',
text: text: [
'Pick one output:' + 'Pick one output:',
response.map((r, idx) => `\n${idx} - ${JSON.stringify(r)}`).join('') + response.map((r, idx) => `\n${idx} - ${JSON.stringify(r)}`).join(''),
'\n\nReply with the number of your choice.', 'Reply with the number of your choice.'
],
timeoutMs: this._options.timeoutMs, timeoutMs: this._options.timeoutMs,
validate: (message) => { validate: (message) => {
const choice = parseInt(message.body) const choice = parseInt(message.body)
@ -110,10 +112,11 @@ export class HumanFeedbackMechanismTwilio<
const { body: selectedOutput } = const { body: selectedOutput } =
await this._twilioClient.sendAndWaitForReply({ await this._twilioClient.sendAndWaitForReply({
name: 'human-feedback-select', name: 'human-feedback-select',
text: text: [
'Select outputs:' + 'Select outputs:',
response.map((r, idx) => `\n${idx} - ${JSON.stringify(r)}`).join('') + response.map((r, idx) => `\n${idx} - ${JSON.stringify(r)}`).join(''),
'\n\nReply with a comma-separated list of the output numbers of your choice.', 'Reply with a comma-separated list of the output numbers of your choice.'
],
timeoutMs: this._options.timeoutMs, timeoutMs: this._options.timeoutMs,
validate: (message) => { validate: (message) => {
const choices = message.body.split(',') const choices = message.body.split(',')

Wyświetl plik

@ -1,7 +1,7 @@
import defaultKy from 'ky' import defaultKy from 'ky'
import { DEFAULT_BOT_NAME } from '@/constants' import { DEFAULT_BOT_NAME } from '@/constants'
import { chunkString, sleep } from '@/utils' import { chunkMultipleStrings, chunkString, sleep } from '@/utils'
export const TWILIO_CONVERSATION_API_BASE_URL = export const TWILIO_CONVERSATION_API_BASE_URL =
'https://conversations.twilio.com/v1' 'https://conversations.twilio.com/v1'
@ -101,9 +101,9 @@ export type TwilioSendAndWaitOptions = {
recipientPhoneNumber?: string recipientPhoneNumber?: string
/** /**
* The text of the message to send. * The text of the message to send (or an array of strings to send as separate messages).
*/ */
text: string text: string | string[]
/** /**
* Friendly name of the conversation. * Friendly name of the conversation.
@ -245,10 +245,16 @@ export class TwilioConversationClient {
text text
}: { }: {
conversationSid: string conversationSid: string
text: string text: string | string[]
maxChunkLength?: number maxChunkLength?: number
}) { }) {
const chunks = chunkString(text, TWILIO_SMS_LENGTH_SOFT_LIMIT) let chunks
if (Array.isArray(text)) {
chunks = chunkMultipleStrings(text, TWILIO_SMS_LENGTH_SOFT_LIMIT)
} else {
chunks = chunkString(text, TWILIO_SMS_LENGTH_SOFT_LIMIT)
}
const out: TwilioConversationMessage[] = [] const out: TwilioConversationMessage[] = []
for (const chunk of chunks) { for (const chunk of chunks) {
const sent = await this.sendMessage({ const sent = await this.sendMessage({

Wyświetl plik

@ -84,8 +84,7 @@ export function chunkString(text: string, maxLength: number): string[] {
if (word.length > maxLength) { if (word.length > maxLength) {
// Truncate the word if it's too long and indicate that it was truncated: // Truncate the word if it's too long and indicate that it was truncated:
chunks.push(word.substring(0, maxLength - 3) + '...') chunks.push(word.substring(0, maxLength - 3) + '...')
} else if ((chunk + word + 1).length > maxLength) { } else if ((chunk + ' ' + word).length > maxLength) {
// +1 accounts for the space between words
chunks.push(chunk.trim()) chunks.push(chunk.trim())
chunk = word chunk = word
} else { } else {
@ -100,6 +99,20 @@ export function chunkString(text: string, maxLength: number): string[] {
return chunks return chunks
} }
/**
* Chunks an array of strings into an array of chunks while preserving existing sections.
*
* @param textSections - array of strings to chunk
* @param maxLength - maximum length of each chunk
* @returns array of chunks
*/
export function chunkMultipleStrings(
textSections: string[],
maxLength: number
): string[] {
return textSections.map((section) => chunkString(section, maxLength)).flat()
}
/** /**
* Stringifies a JSON value for use in an LLM prompt. * Stringifies a JSON value for use in an LLM prompt.
* *