kopia lustrzana https://github.com/transitive-bullshit/chatgpt-api
feat: allow passing array of sections instead of entire message
rodzic
3cce379a2d
commit
f887ea239e
|
@ -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(',')
|
||||||
|
|
|
@ -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({
|
||||||
|
|
17
src/utils.ts
17
src/utils.ts
|
@ -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.
|
||||||
*
|
*
|
||||||
|
|
Ładowanie…
Reference in New Issue