kopia lustrzana https://github.com/transitive-bullshit/chatgpt-api
feat: apply suggestions from PR
rodzic
8ba59411e7
commit
0bfce67a7b
|
@ -17,7 +17,7 @@ export class HumanFeedbackMechanismCLI<
|
|||
/**
|
||||
* Prompt the user to select one of a list of options.
|
||||
*/
|
||||
protected async askUser(
|
||||
protected async _askUser(
|
||||
message: string,
|
||||
choices: HumanFeedbackUserActions[]
|
||||
): Promise<HumanFeedbackUserActions> {
|
||||
|
@ -30,21 +30,21 @@ export class HumanFeedbackMechanismCLI<
|
|||
})
|
||||
}
|
||||
|
||||
protected async edit(output: string): Promise<string> {
|
||||
protected async _edit(output: string): Promise<string> {
|
||||
return editor({
|
||||
message: 'Edit the output:',
|
||||
default: output
|
||||
})
|
||||
}
|
||||
|
||||
protected async annotate(): Promise<string> {
|
||||
protected async _annotate(): Promise<string> {
|
||||
return input({
|
||||
message:
|
||||
'Please leave an annotation (leave blank to skip; press enter to submit):'
|
||||
})
|
||||
}
|
||||
|
||||
protected async selectOne(
|
||||
protected async _selectOne(
|
||||
response: TOutput
|
||||
): Promise<TOutput extends (infer U)[] ? U : never> {
|
||||
if (!Array.isArray(response)) {
|
||||
|
@ -58,7 +58,7 @@ export class HumanFeedbackMechanismCLI<
|
|||
return select({ message: 'Pick one output:', choices })
|
||||
}
|
||||
|
||||
protected async selectN(
|
||||
protected async _selectN(
|
||||
response: TOutput
|
||||
): Promise<TOutput extends any[] ? TOutput : never> {
|
||||
if (!Array.isArray(response)) {
|
||||
|
|
|
@ -11,7 +11,7 @@ export const HumanFeedbackUserActions = {
|
|||
Edit: 'edit',
|
||||
Decline: 'decline',
|
||||
Select: 'select',
|
||||
Exit: 'exit'
|
||||
Abort: 'abort'
|
||||
} as const
|
||||
|
||||
export type HumanFeedbackUserActions =
|
||||
|
@ -25,7 +25,7 @@ export const HumanFeedbackUserActionMessages: Record<
|
|||
[HumanFeedbackUserActions.Edit]: 'Edit the output',
|
||||
[HumanFeedbackUserActions.Decline]: 'Decline the output',
|
||||
[HumanFeedbackUserActions.Select]: 'Select outputs to keep',
|
||||
[HumanFeedbackUserActions.Exit]: 'Exit'
|
||||
[HumanFeedbackUserActions.Abort]: 'Abort'
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -48,9 +48,9 @@ export type HumanFeedbackOptions<T extends HumanFeedbackType, TOutput> = {
|
|||
type?: T
|
||||
|
||||
/**
|
||||
* Whether the user can bail out of the feedback loop.
|
||||
* Whether the user can abort the process.
|
||||
*/
|
||||
bail?: boolean
|
||||
abort?: boolean
|
||||
|
||||
/**
|
||||
* Whether the user can edit the output.
|
||||
|
@ -148,24 +148,24 @@ export abstract class HumanFeedbackMechanism<
|
|||
this._options = options
|
||||
}
|
||||
|
||||
protected abstract selectOne(
|
||||
protected abstract _selectOne(
|
||||
output: TOutput
|
||||
): Promise<TOutput extends any[] ? TOutput[0] : never>
|
||||
|
||||
protected abstract selectN(
|
||||
protected abstract _selectN(
|
||||
response: TOutput
|
||||
): Promise<TOutput extends any[] ? TOutput : never>
|
||||
|
||||
protected abstract annotate(): Promise<string>
|
||||
protected abstract _annotate(): Promise<string>
|
||||
|
||||
protected abstract edit(output: string): Promise<string>
|
||||
protected abstract _edit(output: string): Promise<string>
|
||||
|
||||
protected abstract askUser(
|
||||
protected abstract _askUser(
|
||||
message: string,
|
||||
choices: HumanFeedbackUserActions[]
|
||||
): Promise<HumanFeedbackUserActions>
|
||||
|
||||
protected parseEditedOutput(editedOutput: string): any {
|
||||
protected _parseEditedOutput(editedOutput: string): any {
|
||||
const parsedOutput = JSON.parse(editedOutput)
|
||||
return this._task.outputSchema.parse(parsedOutput)
|
||||
}
|
||||
|
@ -196,14 +196,14 @@ export abstract class HumanFeedbackMechanism<
|
|||
choices.push(HumanFeedbackUserActions.Edit)
|
||||
}
|
||||
|
||||
if (this._options.bail) {
|
||||
choices.push(HumanFeedbackUserActions.Exit)
|
||||
if (this._options.abort) {
|
||||
choices.push(HumanFeedbackUserActions.Abort)
|
||||
}
|
||||
|
||||
const choice =
|
||||
choices.length === 1
|
||||
? HumanFeedbackUserActions.Select
|
||||
: await this.askUser(msg, choices)
|
||||
: await this._askUser(msg, choices)
|
||||
|
||||
const feedback: Record<string, any> = {}
|
||||
|
||||
|
@ -213,8 +213,8 @@ export abstract class HumanFeedbackMechanism<
|
|||
break
|
||||
|
||||
case HumanFeedbackUserActions.Edit: {
|
||||
const editedOutput = await this.edit(stringified)
|
||||
feedback.editedOutput = await this.parseEditedOutput(editedOutput)
|
||||
const editedOutput = await this._edit(stringified)
|
||||
feedback.editedOutput = await this._parseEditedOutput(editedOutput)
|
||||
break
|
||||
}
|
||||
|
||||
|
@ -228,26 +228,26 @@ export abstract class HumanFeedbackMechanism<
|
|||
throw new Error('Expected output to be an array')
|
||||
}
|
||||
|
||||
feedback.selected = await this.selectN(output)
|
||||
feedback.selected = await this._selectN(output)
|
||||
} else if (this._options.type === 'selectOne') {
|
||||
if (!Array.isArray(output)) {
|
||||
throw new Error('Expected output to be an array')
|
||||
}
|
||||
|
||||
feedback.chosen = await this.selectOne(output)
|
||||
feedback.chosen = await this._selectOne(output)
|
||||
}
|
||||
|
||||
break
|
||||
|
||||
case HumanFeedbackUserActions.Exit:
|
||||
throw new Error('Exiting...')
|
||||
case HumanFeedbackUserActions.Abort:
|
||||
throw new Error('Aborting...')
|
||||
|
||||
default:
|
||||
throw new Error(`Unexpected choice: ${choice}`)
|
||||
}
|
||||
|
||||
if (this._options.annotations) {
|
||||
const annotation = await this.annotate()
|
||||
const annotation = await this._annotate()
|
||||
if (annotation) {
|
||||
feedback.annotation = annotation
|
||||
}
|
||||
|
@ -270,7 +270,7 @@ export function withHumanFeedback<TInput, TOutput, V extends HumanFeedbackType>(
|
|||
const finalOptions: HumanFeedbackOptions<V, TOutput> = Object.assign(
|
||||
{
|
||||
type: 'confirm',
|
||||
bail: false,
|
||||
abort: false,
|
||||
editing: false,
|
||||
annotations: false,
|
||||
mechanism: HumanFeedbackMechanismCLI
|
||||
|
|
|
@ -13,22 +13,24 @@ export class HumanFeedbackMechanismSlack<
|
|||
T extends HumanFeedbackType,
|
||||
TOutput = any
|
||||
> extends HumanFeedbackMechanism<T, TOutput> {
|
||||
private slackClient: SlackClient
|
||||
protected _slackClient: SlackClient
|
||||
|
||||
constructor({
|
||||
task,
|
||||
options
|
||||
options,
|
||||
slackClient = new SlackClient()
|
||||
}: {
|
||||
task: BaseTask
|
||||
options: Required<HumanFeedbackOptions<T, TOutput>>
|
||||
slackClient: SlackClient
|
||||
}) {
|
||||
super({ task, options })
|
||||
this.slackClient = new SlackClient()
|
||||
this._slackClient = slackClient
|
||||
}
|
||||
|
||||
protected async annotate(): Promise<string> {
|
||||
protected async _annotate(): Promise<string> {
|
||||
try {
|
||||
const annotation = await this.slackClient.sendAndWaitForReply({
|
||||
const annotation = await this._slackClient.sendAndWaitForReply({
|
||||
text: 'Please leave an annotation (optional):'
|
||||
})
|
||||
return annotation.text
|
||||
|
@ -38,8 +40,8 @@ export class HumanFeedbackMechanismSlack<
|
|||
}
|
||||
}
|
||||
|
||||
protected async edit(): Promise<string> {
|
||||
let { text: editedOutput } = await this.slackClient.sendAndWaitForReply({
|
||||
protected async _edit(): Promise<string> {
|
||||
let { text: editedOutput } = await this._slackClient.sendAndWaitForReply({
|
||||
text: 'Copy and edit the output:'
|
||||
})
|
||||
editedOutput = editedOutput.replace(/```$/g, '')
|
||||
|
@ -47,7 +49,7 @@ export class HumanFeedbackMechanismSlack<
|
|||
return editedOutput
|
||||
}
|
||||
|
||||
protected async askUser(
|
||||
protected async _askUser(
|
||||
message: string,
|
||||
choices: HumanFeedbackUserActions[]
|
||||
): Promise<HumanFeedbackUserActions> {
|
||||
|
@ -59,7 +61,7 @@ export class HumanFeedbackMechanismSlack<
|
|||
.join('\n')
|
||||
message += '\n\n'
|
||||
message += 'Reply with the number of your choice.'
|
||||
const response = await this.slackClient.sendAndWaitForReply({
|
||||
const response = await this._slackClient.sendAndWaitForReply({
|
||||
text: message,
|
||||
validate: (slackMessage) => {
|
||||
const choice = parseInt(slackMessage.text)
|
||||
|
@ -69,15 +71,15 @@ export class HumanFeedbackMechanismSlack<
|
|||
return choices[parseInt(response.text)]
|
||||
}
|
||||
|
||||
protected async selectOne(
|
||||
protected async _selectOne(
|
||||
response: TOutput
|
||||
): Promise<TOutput extends (infer U)[] ? U : never> {
|
||||
if (!Array.isArray(response)) {
|
||||
throw new Error('selectOne called on non-array response')
|
||||
}
|
||||
|
||||
const { text: selectedOutput } = await this.slackClient.sendAndWaitForReply(
|
||||
{
|
||||
const { text: selectedOutput } =
|
||||
await this._slackClient.sendAndWaitForReply({
|
||||
text:
|
||||
'Pick one output:' +
|
||||
response.map((r, idx) => `\n*${idx}* - ${r}`).join('') +
|
||||
|
@ -86,20 +88,19 @@ export class HumanFeedbackMechanismSlack<
|
|||
const choice = parseInt(slackMessage.text)
|
||||
return !isNaN(choice) && choice >= 0 && choice < response.length
|
||||
}
|
||||
}
|
||||
)
|
||||
})
|
||||
return response[parseInt(selectedOutput)]
|
||||
}
|
||||
|
||||
protected async selectN(
|
||||
protected async _selectN(
|
||||
response: TOutput
|
||||
): Promise<TOutput extends any[] ? TOutput : never> {
|
||||
if (!Array.isArray(response)) {
|
||||
throw new Error('selectN called on non-array response')
|
||||
}
|
||||
|
||||
const { text: selectedOutput } = await this.slackClient.sendAndWaitForReply(
|
||||
{
|
||||
const { text: selectedOutput } =
|
||||
await this._slackClient.sendAndWaitForReply({
|
||||
text:
|
||||
'Select outputs:' +
|
||||
response.map((r, idx) => `\n*${idx}* - ${r}`).join('') +
|
||||
|
@ -113,8 +114,7 @@ export class HumanFeedbackMechanismSlack<
|
|||
)
|
||||
})
|
||||
}
|
||||
}
|
||||
)
|
||||
})
|
||||
const chosenOutputs = selectedOutput
|
||||
.split(',')
|
||||
.map((choice) => parseInt(choice))
|
||||
|
|
|
@ -13,22 +13,24 @@ export class HumanFeedbackMechanismTwilio<
|
|||
T extends HumanFeedbackType,
|
||||
TOutput = any
|
||||
> extends HumanFeedbackMechanism<T, TOutput> {
|
||||
private twilioClient: TwilioConversationClient
|
||||
protected _twilioClient: TwilioConversationClient
|
||||
|
||||
constructor({
|
||||
task,
|
||||
options
|
||||
options,
|
||||
twilioClient = new TwilioConversationClient()
|
||||
}: {
|
||||
task: BaseTask
|
||||
options: Required<HumanFeedbackOptions<T, TOutput>>
|
||||
twilioClient: TwilioConversationClient
|
||||
}) {
|
||||
super({ task, options })
|
||||
this.twilioClient = new TwilioConversationClient()
|
||||
this._twilioClient = twilioClient
|
||||
}
|
||||
|
||||
protected async annotate(): Promise<string> {
|
||||
protected async _annotate(): Promise<string> {
|
||||
try {
|
||||
const annotation = await this.twilioClient.sendAndWaitForReply({
|
||||
const annotation = await this._twilioClient.sendAndWaitForReply({
|
||||
name: 'human-feedback-annotation',
|
||||
text: 'Please leave an annotation (optional):'
|
||||
})
|
||||
|
@ -39,8 +41,8 @@ export class HumanFeedbackMechanismTwilio<
|
|||
}
|
||||
}
|
||||
|
||||
protected async edit(): Promise<string> {
|
||||
let { body: editedOutput } = await this.twilioClient.sendAndWaitForReply({
|
||||
protected async _edit(): Promise<string> {
|
||||
let { body: editedOutput } = await this._twilioClient.sendAndWaitForReply({
|
||||
text: 'Copy and edit the output:',
|
||||
name: 'human-feedback-edit'
|
||||
})
|
||||
|
@ -49,7 +51,7 @@ export class HumanFeedbackMechanismTwilio<
|
|||
return editedOutput
|
||||
}
|
||||
|
||||
protected async askUser(
|
||||
protected async _askUser(
|
||||
message: string,
|
||||
choices: HumanFeedbackUserActions[]
|
||||
): Promise<HumanFeedbackUserActions> {
|
||||
|
@ -61,7 +63,7 @@ export class HumanFeedbackMechanismTwilio<
|
|||
.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',
|
||||
text: message,
|
||||
validate: (message) => {
|
||||
|
@ -72,7 +74,7 @@ export class HumanFeedbackMechanismTwilio<
|
|||
return choices[parseInt(response.body)]
|
||||
}
|
||||
|
||||
protected async selectOne(
|
||||
protected async _selectOne(
|
||||
response: TOutput
|
||||
): Promise<TOutput extends (infer U)[] ? U : never> {
|
||||
if (!Array.isArray(response)) {
|
||||
|
@ -80,7 +82,7 @@ export class HumanFeedbackMechanismTwilio<
|
|||
}
|
||||
|
||||
const { body: selectedOutput } =
|
||||
await this.twilioClient.sendAndWaitForReply({
|
||||
await this._twilioClient.sendAndWaitForReply({
|
||||
name: 'human-feedback-select',
|
||||
text:
|
||||
'Pick one output:' +
|
||||
|
@ -94,7 +96,7 @@ export class HumanFeedbackMechanismTwilio<
|
|||
return response[parseInt(selectedOutput)]
|
||||
}
|
||||
|
||||
protected async selectN(
|
||||
protected async _selectN(
|
||||
response: TOutput
|
||||
): Promise<TOutput extends any[] ? TOutput : never> {
|
||||
if (!Array.isArray(response)) {
|
||||
|
@ -102,7 +104,7 @@ export class HumanFeedbackMechanismTwilio<
|
|||
}
|
||||
|
||||
const { body: selectedOutput } =
|
||||
await this.twilioClient.sendAndWaitForReply({
|
||||
await this._twilioClient.sendAndWaitForReply({
|
||||
name: 'human-feedback-select',
|
||||
text:
|
||||
'Select outputs:' +
|
||||
|
|
Ładowanie…
Reference in New Issue