feat: apply suggestions from PR

old-agentic-v1^2
Philipp Burckhardt 2023-06-14 21:22:06 -04:00 zatwierdzone przez Travis Fischer
rodzic 8ba59411e7
commit 0bfce67a7b
4 zmienionych plików z 60 dodań i 58 usunięć

Wyświetl plik

@ -17,7 +17,7 @@ export class HumanFeedbackMechanismCLI<
/** /**
* Prompt the user to select one of a list of options. * Prompt the user to select one of a list of options.
*/ */
protected async askUser( protected async _askUser(
message: string, message: string,
choices: HumanFeedbackUserActions[] choices: HumanFeedbackUserActions[]
): Promise<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({ return editor({
message: 'Edit the output:', message: 'Edit the output:',
default: output default: output
}) })
} }
protected async annotate(): Promise<string> { protected async _annotate(): Promise<string> {
return input({ return input({
message: message:
'Please leave an annotation (leave blank to skip; press enter to submit):' 'Please leave an annotation (leave blank to skip; press enter to submit):'
}) })
} }
protected async selectOne( protected async _selectOne(
response: TOutput response: TOutput
): Promise<TOutput extends (infer U)[] ? U : never> { ): Promise<TOutput extends (infer U)[] ? U : never> {
if (!Array.isArray(response)) { if (!Array.isArray(response)) {
@ -58,7 +58,7 @@ export class HumanFeedbackMechanismCLI<
return select({ message: 'Pick one output:', choices }) return select({ message: 'Pick one output:', choices })
} }
protected async selectN( protected async _selectN(
response: TOutput response: TOutput
): Promise<TOutput extends any[] ? TOutput : never> { ): Promise<TOutput extends any[] ? TOutput : never> {
if (!Array.isArray(response)) { if (!Array.isArray(response)) {

Wyświetl plik

@ -11,7 +11,7 @@ export const HumanFeedbackUserActions = {
Edit: 'edit', Edit: 'edit',
Decline: 'decline', Decline: 'decline',
Select: 'select', Select: 'select',
Exit: 'exit' Abort: 'abort'
} as const } as const
export type HumanFeedbackUserActions = export type HumanFeedbackUserActions =
@ -25,7 +25,7 @@ export const HumanFeedbackUserActionMessages: Record<
[HumanFeedbackUserActions.Edit]: 'Edit the output', [HumanFeedbackUserActions.Edit]: 'Edit the output',
[HumanFeedbackUserActions.Decline]: 'Decline the output', [HumanFeedbackUserActions.Decline]: 'Decline the output',
[HumanFeedbackUserActions.Select]: 'Select outputs to keep', [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 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. * Whether the user can edit the output.
@ -148,24 +148,24 @@ export abstract class HumanFeedbackMechanism<
this._options = options this._options = options
} }
protected abstract selectOne( protected abstract _selectOne(
output: TOutput output: TOutput
): Promise<TOutput extends any[] ? TOutput[0] : never> ): Promise<TOutput extends any[] ? TOutput[0] : never>
protected abstract selectN( protected abstract _selectN(
response: TOutput response: TOutput
): Promise<TOutput extends any[] ? TOutput : never> ): 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, message: string,
choices: HumanFeedbackUserActions[] choices: HumanFeedbackUserActions[]
): Promise<HumanFeedbackUserActions> ): Promise<HumanFeedbackUserActions>
protected parseEditedOutput(editedOutput: string): any { protected _parseEditedOutput(editedOutput: string): any {
const parsedOutput = JSON.parse(editedOutput) const parsedOutput = JSON.parse(editedOutput)
return this._task.outputSchema.parse(parsedOutput) return this._task.outputSchema.parse(parsedOutput)
} }
@ -196,14 +196,14 @@ export abstract class HumanFeedbackMechanism<
choices.push(HumanFeedbackUserActions.Edit) choices.push(HumanFeedbackUserActions.Edit)
} }
if (this._options.bail) { if (this._options.abort) {
choices.push(HumanFeedbackUserActions.Exit) choices.push(HumanFeedbackUserActions.Abort)
} }
const choice = const choice =
choices.length === 1 choices.length === 1
? HumanFeedbackUserActions.Select ? HumanFeedbackUserActions.Select
: await this.askUser(msg, choices) : await this._askUser(msg, choices)
const feedback: Record<string, any> = {} const feedback: Record<string, any> = {}
@ -213,8 +213,8 @@ export abstract class HumanFeedbackMechanism<
break break
case HumanFeedbackUserActions.Edit: { case HumanFeedbackUserActions.Edit: {
const editedOutput = await this.edit(stringified) const editedOutput = await this._edit(stringified)
feedback.editedOutput = await this.parseEditedOutput(editedOutput) feedback.editedOutput = await this._parseEditedOutput(editedOutput)
break break
} }
@ -228,26 +228,26 @@ export abstract class HumanFeedbackMechanism<
throw new Error('Expected output to be an array') 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') { } else if (this._options.type === 'selectOne') {
if (!Array.isArray(output)) { if (!Array.isArray(output)) {
throw new Error('Expected output to be an array') throw new Error('Expected output to be an array')
} }
feedback.chosen = await this.selectOne(output) feedback.chosen = await this._selectOne(output)
} }
break break
case HumanFeedbackUserActions.Exit: case HumanFeedbackUserActions.Abort:
throw new Error('Exiting...') throw new Error('Aborting...')
default: default:
throw new Error(`Unexpected choice: ${choice}`) throw new Error(`Unexpected choice: ${choice}`)
} }
if (this._options.annotations) { if (this._options.annotations) {
const annotation = await this.annotate() const annotation = await this._annotate()
if (annotation) { if (annotation) {
feedback.annotation = annotation feedback.annotation = annotation
} }
@ -270,7 +270,7 @@ export function withHumanFeedback<TInput, TOutput, V extends HumanFeedbackType>(
const finalOptions: HumanFeedbackOptions<V, TOutput> = Object.assign( const finalOptions: HumanFeedbackOptions<V, TOutput> = Object.assign(
{ {
type: 'confirm', type: 'confirm',
bail: false, abort: false,
editing: false, editing: false,
annotations: false, annotations: false,
mechanism: HumanFeedbackMechanismCLI mechanism: HumanFeedbackMechanismCLI

Wyświetl plik

@ -13,22 +13,24 @@ export class HumanFeedbackMechanismSlack<
T extends HumanFeedbackType, T extends HumanFeedbackType,
TOutput = any TOutput = any
> extends HumanFeedbackMechanism<T, TOutput> { > extends HumanFeedbackMechanism<T, TOutput> {
private slackClient: SlackClient protected _slackClient: SlackClient
constructor({ constructor({
task, task,
options options,
slackClient = new SlackClient()
}: { }: {
task: BaseTask task: BaseTask
options: Required<HumanFeedbackOptions<T, TOutput>> options: Required<HumanFeedbackOptions<T, TOutput>>
slackClient: SlackClient
}) { }) {
super({ task, options }) super({ task, options })
this.slackClient = new SlackClient() this._slackClient = slackClient
} }
protected async annotate(): Promise<string> { protected async _annotate(): Promise<string> {
try { try {
const annotation = await this.slackClient.sendAndWaitForReply({ const annotation = await this._slackClient.sendAndWaitForReply({
text: 'Please leave an annotation (optional):' text: 'Please leave an annotation (optional):'
}) })
return annotation.text return annotation.text
@ -38,8 +40,8 @@ export class HumanFeedbackMechanismSlack<
} }
} }
protected async edit(): Promise<string> { protected async _edit(): Promise<string> {
let { text: editedOutput } = await this.slackClient.sendAndWaitForReply({ let { text: editedOutput } = await this._slackClient.sendAndWaitForReply({
text: 'Copy and edit the output:' text: 'Copy and edit the output:'
}) })
editedOutput = editedOutput.replace(/```$/g, '') editedOutput = editedOutput.replace(/```$/g, '')
@ -47,7 +49,7 @@ export class HumanFeedbackMechanismSlack<
return editedOutput return editedOutput
} }
protected async askUser( protected async _askUser(
message: string, message: string,
choices: HumanFeedbackUserActions[] choices: HumanFeedbackUserActions[]
): Promise<HumanFeedbackUserActions> { ): Promise<HumanFeedbackUserActions> {
@ -59,7 +61,7 @@ export class HumanFeedbackMechanismSlack<
.join('\n') .join('\n')
message += '\n\n' message += '\n\n'
message += 'Reply with the number of your choice.' message += 'Reply with the number of your choice.'
const response = await this.slackClient.sendAndWaitForReply({ const response = await this._slackClient.sendAndWaitForReply({
text: message, text: message,
validate: (slackMessage) => { validate: (slackMessage) => {
const choice = parseInt(slackMessage.text) const choice = parseInt(slackMessage.text)
@ -69,15 +71,15 @@ export class HumanFeedbackMechanismSlack<
return choices[parseInt(response.text)] return choices[parseInt(response.text)]
} }
protected async selectOne( protected async _selectOne(
response: TOutput response: TOutput
): Promise<TOutput extends (infer U)[] ? U : never> { ): Promise<TOutput extends (infer U)[] ? U : never> {
if (!Array.isArray(response)) { if (!Array.isArray(response)) {
throw new Error('selectOne called on non-array 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: text:
'Pick one output:' + 'Pick one output:' +
response.map((r, idx) => `\n*${idx}* - ${r}`).join('') + response.map((r, idx) => `\n*${idx}* - ${r}`).join('') +
@ -86,20 +88,19 @@ export class HumanFeedbackMechanismSlack<
const choice = parseInt(slackMessage.text) const choice = parseInt(slackMessage.text)
return !isNaN(choice) && choice >= 0 && choice < response.length return !isNaN(choice) && choice >= 0 && choice < response.length
} }
} })
)
return response[parseInt(selectedOutput)] return response[parseInt(selectedOutput)]
} }
protected async selectN( protected async _selectN(
response: TOutput response: TOutput
): Promise<TOutput extends any[] ? TOutput : never> { ): Promise<TOutput extends any[] ? TOutput : never> {
if (!Array.isArray(response)) { if (!Array.isArray(response)) {
throw new Error('selectN called on non-array 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: text:
'Select outputs:' + 'Select outputs:' +
response.map((r, idx) => `\n*${idx}* - ${r}`).join('') + response.map((r, idx) => `\n*${idx}* - ${r}`).join('') +
@ -113,8 +114,7 @@ export class HumanFeedbackMechanismSlack<
) )
}) })
} }
} })
)
const chosenOutputs = selectedOutput const chosenOutputs = selectedOutput
.split(',') .split(',')
.map((choice) => parseInt(choice)) .map((choice) => parseInt(choice))

Wyświetl plik

@ -13,22 +13,24 @@ export class HumanFeedbackMechanismTwilio<
T extends HumanFeedbackType, T extends HumanFeedbackType,
TOutput = any TOutput = any
> extends HumanFeedbackMechanism<T, TOutput> { > extends HumanFeedbackMechanism<T, TOutput> {
private twilioClient: TwilioConversationClient protected _twilioClient: TwilioConversationClient
constructor({ constructor({
task, task,
options options,
twilioClient = new TwilioConversationClient()
}: { }: {
task: BaseTask task: BaseTask
options: Required<HumanFeedbackOptions<T, TOutput>> options: Required<HumanFeedbackOptions<T, TOutput>>
twilioClient: TwilioConversationClient
}) { }) {
super({ task, options }) super({ task, options })
this.twilioClient = new TwilioConversationClient() this._twilioClient = twilioClient
} }
protected async annotate(): Promise<string> { protected async _annotate(): Promise<string> {
try { try {
const annotation = await this.twilioClient.sendAndWaitForReply({ const annotation = await this._twilioClient.sendAndWaitForReply({
name: 'human-feedback-annotation', name: 'human-feedback-annotation',
text: 'Please leave an annotation (optional):' text: 'Please leave an annotation (optional):'
}) })
@ -39,8 +41,8 @@ export class HumanFeedbackMechanismTwilio<
} }
} }
protected async edit(): Promise<string> { protected async _edit(): Promise<string> {
let { body: editedOutput } = await this.twilioClient.sendAndWaitForReply({ let { body: editedOutput } = await this._twilioClient.sendAndWaitForReply({
text: 'Copy and edit the output:', text: 'Copy and edit the output:',
name: 'human-feedback-edit' name: 'human-feedback-edit'
}) })
@ -49,7 +51,7 @@ export class HumanFeedbackMechanismTwilio<
return editedOutput return editedOutput
} }
protected async askUser( protected async _askUser(
message: string, message: string,
choices: HumanFeedbackUserActions[] choices: HumanFeedbackUserActions[]
): Promise<HumanFeedbackUserActions> { ): Promise<HumanFeedbackUserActions> {
@ -61,7 +63,7 @@ export class HumanFeedbackMechanismTwilio<
.join('\n') .join('\n')
message += '\n\n' message += '\n\n'
message += 'Reply with the number of your choice.' 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,
validate: (message) => { validate: (message) => {
@ -72,7 +74,7 @@ export class HumanFeedbackMechanismTwilio<
return choices[parseInt(response.body)] return choices[parseInt(response.body)]
} }
protected async selectOne( protected async _selectOne(
response: TOutput response: TOutput
): Promise<TOutput extends (infer U)[] ? U : never> { ): Promise<TOutput extends (infer U)[] ? U : never> {
if (!Array.isArray(response)) { if (!Array.isArray(response)) {
@ -80,7 +82,7 @@ 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:' +
@ -94,7 +96,7 @@ export class HumanFeedbackMechanismTwilio<
return response[parseInt(selectedOutput)] return response[parseInt(selectedOutput)]
} }
protected async selectN( protected async _selectN(
response: TOutput response: TOutput
): Promise<TOutput extends any[] ? TOutput : never> { ): Promise<TOutput extends any[] ? TOutput : never> {
if (!Array.isArray(response)) { if (!Array.isArray(response)) {
@ -102,7 +104,7 @@ 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:' +