Skip to content

Commit

Permalink
V2 parser fixes (#522)
Browse files Browse the repository at this point in the history
  • Loading branch information
sceuick authored Jul 20, 2023
1 parent 4a1d992 commit 46f37ba
Show file tree
Hide file tree
Showing 6 changed files with 75 additions and 44 deletions.
18 changes: 9 additions & 9 deletions common/grammar.ts
Original file line number Diff line number Diff line change
Expand Up @@ -88,25 +88,25 @@ HistoryRef = OP prop:HistoryProperty CL { return { kind: 'history-prop', prop }
BotProperty "bot-prop" = "." prop:("name"i / Persona / "i"i) { return prop.toLowerCase() }
HistoryProperty "history-prop" = "." prop:(Message / "dialogue"i / "name"i / "isuser"i / "isbot"i / "i"i) { return prop.toLowerCase() }
Character "character" = "char"i / "character"i / "bot"i { return "char" }
Character "character" = ("char"i / "character"i / "bot"i) { return "char" }
User "user" = "user"i { return "user" }
Scenario "scenario" = "scenario"i { return "scenario" }
Impersonate "impersonating" = "impersonate"i / "impersonating"i { return "impersonating" }
Persona "personality" = "personality"i / "persona"i { return "personality" }
AllPersona "all_personalities" = "all_personas"i / "all_personalities"i { return "all_personalities" }
Dialogue "example_dialogue" = "samplechat"i / "example_dialogue"i { return "example_dialogue" }
Impersonate "impersonating" = ("impersonate"i / "impersonating"i) { return "impersonating" }
Persona "personality" = ("personality"i / "persona"i) { return "personality" }
AllPersona "all_personalities" = ("all_personas"i / "all_personalities"i) { return "all_personalities" }
Dialogue "example_dialogue" = ("samplechat"i / "example_dialogue"i) { return "example_dialogue" }
Instruction "instruction" = "system_prompt"i { return "system_prompt" }
Jailbreak "ujb" = "ujb"i / "system_note"i { return "ujb" }
Jailbreak "ujb" = ("ujb"i / "system_note"i) { return "ujb" }
Post "post" = "post"i { return "post" }
Memory "memory" = "memory"i { return "memory" }
Message "message" = "msg"i / "message"i / "text"i { return "message" }
Message "message" = ("msg"i / "message"i / "text"i) { return "message" }
ChatAge "chat-age" = "chat_age"i { return "chat_age" }
IdleDuration "idle-duration" = "idle_duration"i { return "idle_duration" }
ChatEmbed "chat-embed" = "chat_embed"i { return "chat_embed" }
UserEmbed "user-embed" = "user_embed"i { return "user_embed" }
Random "random" = "random:"i WS words:CSV { return { kind: "random", values: words } }
Roll "roll" = ("roll"i / "dice"i) WS "d"|0..1| max:[0-9]|0..10| { return { kind: 'roll', max: +max.join('') || 20 } }
Random "random" = "random"i ":"? WS words:CSV { return { kind: "random", values: words } }
Roll "roll" = ("roll"i / "dice"i) WS "d"|0..1| max:[0-9]|0..10| { return { kind: 'roll', values: +max.join('') || 20 } }
// Iterable entities
Bots "bots" = ( "bots"i ) { return "bots" }
Expand Down
10 changes: 7 additions & 3 deletions common/prompt.ts
Original file line number Diff line number Diff line change
Expand Up @@ -214,9 +214,13 @@ export function getTemplate(
) {
const isChat = OPENAI_CHAT_MODELS[opts.settings?.oaiModel || ''] ?? false
const useGaslight = (opts.settings?.service === 'openai' && isChat) || opts.settings?.useGaslight
const gaslight = opts.settings?.gaslight || defaultPresets.openai.gaslight

const template = useGaslight ? gaslight : defaultTemplate
const gaslight = opts.settings?.gaslight || defaultPresets.openai.gaslight
const template = useGaslight
? gaslight
: opts.settings?.useTemplateParser
? opts.settings.gaslight ?? defaultTemplate
: defaultTemplate
return ensureValidTemplate(template, parts)
}

Expand Down Expand Up @@ -348,7 +352,7 @@ export function ensureValidTemplate(
const skips = new Set(skip || [])
let hasScenario = !!template.match(HOLDERS.scenario)
let hasPersona = !!template.match(HOLDERS.persona)
let hasHistory = !!template.match(HOLDERS.history)
let hasHistory = !!template.match(HOLDERS.history) || !!template.match(/{{\#each msg}}/gi)
let hasPost = !!template.match(HOLDERS.post)
let hasUjb = !!template.match(HOLDERS.ujb)
let hasUserEmbed = !!template.match(HOLDERS.userEmbed)
Expand Down
12 changes: 8 additions & 4 deletions common/template-parser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -126,11 +126,14 @@ function renderProp(node: CNode, opts: ParseOpts, entity: unknown, i: number) {
case 'history-prop': {
const line = entity as string
switch (node.prop) {
case 'i':
case 'i': {
return i.toString()
}

case 'message':
return entity as string
case 'message': {
const index = line.indexOf(':')
return line.slice(index + 1).trim()
}

case 'name': {
const index = line.indexOf(':')
Expand All @@ -143,12 +146,13 @@ function renderProp(node: CNode, opts: ParseOpts, entity: unknown, i: number) {
}

case 'isbot':
case 'isuser':
case 'isuser': {
const index = line.indexOf(':')
const name = line.slice(0, index)
const sender = opts.impersonate?.name ?? opts.sender.handle
const match = name === sender
return node.prop === 'isuser' ? match : !match
}
}
}
}
Expand Down
33 changes: 20 additions & 13 deletions tests/__snapshots__/prompt.spec.js.snap
Original file line number Diff line number Diff line change
Expand Up @@ -172,13 +172,16 @@ OtherBot:"
exports[`Prompt building will include example dialogue with omitted from template 1`] = `
"*** V2 Parser ***
OtherBot's Persona: OtherBot replies a lot
Scenario: MAIN MainChar
Facts:ENTRY ONE
GASLIGHT
ChatOwner
OtherBot
Facts: ENTRY ONE
ENTRY TIE
ENTRY THREE
How OtherBot speaks: SAMPLECHAT OtherBot
Scenario: MAIN MainChar
OtherBot's persona: OtherBot replies a lot
How OtherBot speaks:
SAMPLECHAT OtherBot
<START>
MainChar: FIRST
ChatOwner: 1-TRIGGER
Expand Down Expand Up @@ -279,10 +282,11 @@ OtherBot:"
exports[`Prompt building will include sample chat when gaslight does not contain sample chat placeholder 1`] = `
"*** V2 Parser ***
OtherBot's Persona: OtherBot replies a lot
Gaslight
Scenario: MAIN MainChar
How OtherBot speaks: SAMPLECHAT OtherBot
OtherBot's persona: OtherBot replies a lot
How OtherBot speaks:
SAMPLECHAT OtherBot
<START>
MainChar: FIRST
ChatOwner: SECOND
Expand Down Expand Up @@ -392,13 +396,16 @@ OtherBot:"
exports[`Prompt building will not use the gaslight when set to false 1`] = `
"*** V2 Parser ***
OtherBot's Persona: OtherBot replies a lot
Scenario: MAIN MainChar
Facts:ENTRY ONE
GASLIGHT
ChatOwner
OtherBot
Facts: ENTRY ONE
ENTRY TIE
ENTRY THREE
How OtherBot speaks: SAMPLECHAT OtherBot
Scenario: MAIN MainChar
OtherBot's persona: OtherBot replies a lot
How OtherBot speaks:
SAMPLECHAT OtherBot
<START>
MainChar: FIRST
ChatOwner: 1-TRIGGER
Expand Down
18 changes: 8 additions & 10 deletions web/shared/GenerationSettings.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -446,16 +446,14 @@ const PromptSettings: Component<Props> = (props) => {
/>
</Card>

<Card class="flex flex-col gap-4">
<Show when={cfg.parser && canUseParser}>
<Toggle
fieldName="useTemplateParser"
value={props.inherit?.useTemplateParser}
label="Use Template Parser (Experimental)"
helperText="The V2 parser supports additional placeholders (#each, #if, random, roll, ...)."
onChange={(v) => setV2(v)}
/>
</Show>
<Card class="flex flex-col gap-4" hide={!cfg.parser || !canUseParser}>
<Toggle
fieldName="useTemplateParser"
value={props.inherit?.useTemplateParser}
label="Use Template Parser (Experimental)"
helperText="This will override your prompt. The V2 parser supports additional placeholders (#each, #if, random, roll, ...)."
onChange={(v) => setV2(v)}
/>

<PromptEditor
fieldName="gaslight"
Expand Down
28 changes: 23 additions & 5 deletions web/shared/PromptEditor/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import { getAISettingServices, toMap } from '../util'
import { useRootModal } from '../hooks'
import Modal from '../Modal'
import { HelpCircle } from 'lucide-solid'
import { SolidCard } from '../Card'
import { TitleCard } from '../Card'
import Button from '../Button'
import { ParseOpts, parseTemplate } from '/common/template-parser'
import { toBotMsg, toChar, toChat, toPersona, toProfile, toUser, toUserMsg } from '/common/dummy'
Expand Down Expand Up @@ -50,8 +50,8 @@ const placeholders = {
} satisfies Record<string, Placeholder>

const v2placeholders = {
roll: { required: false, limit: Infinity },
random: { required: false, limit: Infinity },
roll: { required: false, limit: Infinity, inserted: 'roll 20' },
random: { required: false, limit: Infinity, inserted: 'random: a,b,c' },
'each message': { required: false, limit: 1, inserted: `#each msg}} {{/each` },
'each bot': { required: false, limit: 1, inserted: `#each bot}} {{/each` },
} satisfies Record<string, Placeholder>
Expand All @@ -74,6 +74,24 @@ const v2helpers: { [key in InterpV2]?: JSX.Element | string } = {
roll: 'Produces a random number. Defaults to "d20". To use a custom number: {{roll [number]}}. E.g.: {{roll 1000}}',
random:
'Produces a random word from a comma-separated list. E.g.: {{random happy, sad, jealous, angry}}',
'each bot': (
<>
Suported properties: <code>{`{{.name}} {{.persona}}`}</code>
<br />
Example: <code>{`{{#each bot}}{{.name}}'s personality: {{.persona}}{{/each}}`}</code>
</>
),
'each message': (
<>
{' '}
Supported properties: <code>{`{{.msg}} {{.name}} {{.isuser}} {{.isbot}} {{.i}}`}</code> <br />
You can use <b>conditions</b> for isbot and isuser. E.g.{' '}
<code>{`{{#if .isuser}} ... {{/if}}`}</code>
<br />
Full example:{' '}
<code>{`{{#each msg}}{{#if .isuser}}User: {{.msg}}{{/if}}{{#if .isbot}}Bot: {{.msg}}{{/if}}{{/each}}`}</code>
</>
),
}

type HolderName = keyof typeof placeholders
Expand Down Expand Up @@ -294,9 +312,9 @@ const HelpModal: Component<{
<div class="flex w-full flex-col gap-1 text-sm">
<For each={items()}>
{([interp, help]) => (
<SolidCard>
<TitleCard>
<FormLabel fieldName={interp} label={interp} helperText={help} />
</SolidCard>
</TitleCard>
)}
</For>
</div>
Expand Down

0 comments on commit 46f37ba

Please sign in to comment.