Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions common/adapters.ts
Original file line number Diff line number Diff line change
Expand Up @@ -366,8 +366,8 @@ export const ADAPTER_LABELS: { [key in AIAdapter]: string } = {
export const FORMAT_LABEL: { [key in ThirdPartyFormat]: string } = {
kobold: 'Kobold',
openai: 'OpenAI (Completion)',
'openai-chat': 'OpenAI Compatible (Chat - Legacy)',
'openai-chatv2': 'OpenAI Compatible (Chat)',
'openai-chat': 'OpenAI Compat (Chat - Legacy)',
'openai-chatv2': 'OpenAI Compat (Chat)',
aphrodite: 'Aphrodite',
arli: 'ArliAI',
claude: 'Claude (Legacy)',
Expand Down
8 changes: 6 additions & 2 deletions common/prompt.ts
Original file line number Diff line number Diff line change
Expand Up @@ -306,7 +306,11 @@ export type AssembledPrompt = Awaited<ReturnType<typeof assemblePrompt>>
* @param lines Always in time-ascending order (oldest to newest)
* @returns
*/
export async function assemblePrompt(opts: GenerateRequestV2, encoder: TokenCounter) {
export async function assemblePrompt(
opts: GenerateRequestV2,
encoder: TokenCounter,
chat?: boolean
) {
const post = createPostPrompt(opts)
const template = getTemplate(opts)

Expand All @@ -320,7 +324,7 @@ export async function assemblePrompt(opts: GenerateRequestV2, encoder: TokenCoun
lastMessage: opts.lastMessage,
encoder,
jsonValues: undefined,
format: getFormatOverride(opts),
format: chat ? 'None' : getFormatOverride(opts),
})

return {
Expand Down
4 changes: 2 additions & 2 deletions common/providers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ export const KNOWN_SELF_HOST: Record<string, ProviderDefinition> = {
name: 'Self-Host / OpenAI Compatible',
url: '',
formats: [
{ type: 'format', name: 'OpenAI Compatible', url: '', value: 'openai-chatv2' },
{ type: 'format', name: 'OpenAI Compat', url: '', value: 'openai-chatv2' },
{ type: 'format', value: 'tabby', url: 'http://localhost:5000/v1' },
{ type: 'format', value: 'aphrodite', url: 'http://localhost:2242/v1' },
{ type: 'format', value: 'vllm', url: 'http://localhost:8000/v1' },
Expand All @@ -127,7 +127,7 @@ export const KNOWN_SELF_HOST: Record<string, ProviderDefinition> = {

export const CUSTOM_PROVIDERS: Record<string, ProviderDefinition> = {
'openai-chatv2': {
name: 'OpenAI Compatible',
name: 'OpenAI Compat',
formats: [
{
type: 'format',
Expand Down
24 changes: 15 additions & 9 deletions common/template-messages.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import { findLast } from './util'
import { GenerateRequestV2 } from '/srv/adapter/type'

export async function toChatMessages(req: GenerateRequestV2, counter: TokenCounter) {
const assembled = await assemblePrompt(req, counter)
const assembled = await assemblePrompt(req, counter, true)

const { sections } = assembled
const {
Expand All @@ -20,15 +20,21 @@ export async function toChatMessages(req: GenerateRequestV2, counter: TokenCount
const systemPrompt = strictSystem.join('').trim().replace(/\n\n+/g, '\n\n')
const postSystem = post_system.join('').trim().replace(/\n\n+/g, '\n\n')

if (systemPrompt) {
messages.push({
role: 'system',
content: strictSystem.join('').trim().replace(/\n\n+/g, '\n\n'),
})
}
// Legacy:
// if (systemPrompt) {
// messages.push({
// role: 'system',
// content: strictSystem.join('').trim().replace(/\n\n+/g, '\n\n'),
// })
// }

// if (postSystem) {
// messages.push({ role: 'user', content: postSystem })
// }

if (postSystem) {
messages.push({ role: 'user', content: postSystem })
if (systemPrompt || postSystem) {
const joined = [systemPrompt || '', postSystem || ''].filter((m) => !!m.trim()).join('\n\n')
messages.push({ role: 'system', content: joined.trim().replace(/\n\n+/g, '\n\n') })
}

const sender = (req.impersonate?.name || req.sender.handle) + ':'
Expand Down
12 changes: 6 additions & 6 deletions srv/api/chat/remove.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,13 +21,13 @@ export const deleteMessagesV2 = handle(async ({ body, params, userId }) => {
const graph = toQuickGraph(messages, body.leafId)
const edges = getDeletionChanges(graph, body.ids)

for (const id of body.ids) {
const msg = graph.tree[id]
// for (const id of body.ids) {
// const msg = graph.tree[id]

if (!msg) {
throw new StatusError(`Bad delete request: Message ID not found`, 400)
}
}
// if (!msg) {
// throw new StatusError(`Bad delete request: Message ID not found`, 400)
// }
// }

if (!body.soft) {
// No parents get updated in a 'tail' delete
Expand Down
5 changes: 0 additions & 5 deletions srv/db/client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -91,11 +91,6 @@ export async function createIndexes() {
await db('image-preset').createIndex({ userId: 1 }, { name: 'image-preset_userId' })

await db('chat-message').createIndex({ chatId: 1 }, { name: 'chatmessages_chatId' })
await db('chat-message').createIndex(
{ chatId: 1, parent: 1 },
{ name: 'chatmessages_chatId_parent' }
)
await db('chat-message').createIndex({ parent: 1 }, { name: 'chatmessages_parent' })
await db('chat-message').createIndex(
{ chatId: 1, kind: 1, createdAt: -1 },
{ name: 'chatmessages_chatId_kind_createdAt' }
Expand Down
18 changes: 11 additions & 7 deletions web/pages/Character/DownloadModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import { exportCharacter } from '/common/characters'
import { charsApi } from '/web/store/data/chars'
import { toastStore } from '/web/store'
import { downloadCharCard } from './util'
import { downloadJson } from '/web/shared/util'

type CharacterFileType = 'png' | 'json'

Expand Down Expand Up @@ -84,8 +85,7 @@ export const DownloadModal: Component<{
if (!char()) return

const json = charToJson(char()!, format())
const encode = `data:text/json;charset=utf-8,${encodeURIComponent(json)}`
return encode
return json
// const url = URL.createObjectURL(new Blob([json], { type: 'text/json' }))
// return url
})
Expand All @@ -102,11 +102,15 @@ export const DownloadModal: Component<{
</Button>
<Switch>
<Match when={fileType() === 'json'}>
<a href={objectUrl()} download={`${char()!.name}.json`}>
<Button>
<Save /> Download (JSON)
</Button>
</a>
<Button
onClick={() => {
const downloadableChar = objectUrl()
if (!downloadableChar) return
downloadJson(downloadableChar, `${char()?.name}.json`)
}}
>
<Save /> Download (JSON)
</Button>
</Match>

<Match when={fileType() === 'png'}>
Expand Down
34 changes: 21 additions & 13 deletions web/pages/Chat/ChatExport.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,19 +3,20 @@ import { Component, createMemo } from 'solid-js'
import Button from '../../shared/Button'
import Modal from '../../shared/Modal'
import { characterStore, chatStore, msgStore } from '../../store'
import { resolveChatPath } from '/common/chat'
import { ChatTree } from '/common/chat'
import { useAppContext } from '/web/store/context'
import { downloadJson } from '/web/shared/util'

const ChatExport: Component<{ show: boolean; close: () => void }> = (props) => {
const [ctx] = useAppContext()
const chats = chatStore.getState()
const chars = characterStore.getState().characters
const msgs = msgStore.getState()

const json = createMemo(() => {
const downloadableChat = createMemo(() => {
const graph = msgs.graph
const chat = ctx.active?.chat
const messages = resolveChatPath(graph.tree, msgs.msgs.slice(-1)[0]._id)
const messages = getAllMessasges(graph.tree)

const json = {
name: 'Exported',
Expand Down Expand Up @@ -44,27 +45,34 @@ const ChatExport: Component<{ show: boolean; close: () => void }> = (props) => {
})),
}

return encodeURIComponent(JSON.stringify(json, null, 2))
return json
})

const download = () => {
const chat = downloadableChat()
downloadJson(chat, `chat-${ctx.active?.chat._id.slice(0, 4)}.json`)
}

const Footer = (
<>
<Button schema="secondary" onClick={props.close}>
Close
</Button>
<a
href={`data:text/json:charset=utf-8,${json()}`}
download={`chat-${ctx.active?.chat._id.slice(0, 4)}.json`}
onClick={props.close}
>
<Button>
<Download /> Download
</Button>
</a>

<Button onClick={download}>
<Download /> Download
</Button>
</>
)

return <Modal show={props.show} close={props.close} title="Export Chat" footer={Footer}></Modal>
}

export default ChatExport

function getAllMessasges(tree: ChatTree) {
const messages = Object.values(tree)
.map((item) => item.msg)
.sort((l, r) => l.createdAt.localeCompare(r.createdAt))
return messages
}
18 changes: 11 additions & 7 deletions web/pages/Profile/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import Button from '../../shared/Button'
import FileInput, { FileInputResult, getFileAsString } from '../../shared/FileInput'
import Modal, { RootModal } from '../../shared/Modal'
import TextInput from '../../shared/TextInput'
import { setComponentPageTitle } from '../../shared/util'
import { downloadJson, setComponentPageTitle } from '../../shared/util'
import { adminStore, pageStore, settingStore, toastStore, userStore } from '../../store'
import { Pill, TitleCard } from '/web/shared/Card'
import { useNavigate, useSearchParams } from '@solidjs/router'
Expand Down Expand Up @@ -107,7 +107,7 @@ const ProfilePage: Component<{ footer?: (children: any) => void }> = (props) =>
const [del, setDel] = createSignal(false)
const [avatar, setAvatar] = createSignal<File | undefined>()
const [importing, setImporting] = createSignal(false)
const [dataHref, setDataHref] = createSignal('')
const [downloadData, setDownloadData] = createSignal<any>()
const google = useGoogleReady()

const canuseGoogle = createMemo(
Expand Down Expand Up @@ -358,8 +358,7 @@ const ProfilePage: Component<{ footer?: (children: any) => void }> = (props) =>
schema="success"
onClick={async () => {
const data = await localApi.getGuestData()
const href = await localApi.prepareJsonHref(data)
setDataHref(href)
setDownloadData(data)
}}
>
Prepare Backup
Expand All @@ -369,12 +368,17 @@ const ProfilePage: Component<{ footer?: (children: any) => void }> = (props) =>
</Button>
</div>

<Show when={!!dataHref()} fallback={<span class="text-500">Backup Not Ready</span>}>
<Show
when={!!downloadData()}
fallback={<span class="text-500">Backup Not Ready</span>}
>
<div class="flex justify-center">
<a
class="link flex gap-1"
href={dataHref()}
download={`guest-data-${Date.now()}.json`}
onClick={() => {
const data = downloadData()
downloadJson(data, `guest-data-${Date.now()}.json`)
}}
>
Download Guest Data <Download size={16} />
</a>
Expand Down
2 changes: 1 addition & 1 deletion web/store/data/presets.ts
Original file line number Diff line number Diff line change
Expand Up @@ -248,7 +248,7 @@ async function getModelListByPreset(preset: Partial<AppSchema.UserGenPreset>, fo
id: preset._id || '',
providerId: preset.providerId,
url,
key: '',
key: isLoggedIn() ? '' : provider.key,
})

return { list: result.models, url, data: result.data }
Expand Down
1 change: 1 addition & 0 deletions web/store/data/storage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -192,6 +192,7 @@ async function getGuestInitEntities(config?: AppSchema.AppConfig) {
if (model) {
const preset: AppSchema.UserGenPreset = {
...model?.preset,
modelFormat: 'None',
service: model?.service,
_id: v4(),
name: 'My Preset',
Expand Down
11 changes: 6 additions & 5 deletions web/store/settings.ts
Original file line number Diff line number Diff line change
Expand Up @@ -195,7 +195,7 @@ export const settingStore = createStore<SettingState>(
}

if (!isMaint) {
handlePostInit(init, caches)
handlePostInit(init, caches, userId === 'anon')
}

const maint = init.config?.maintenance
Expand Down Expand Up @@ -485,19 +485,20 @@ async function loadUserCachedEntities() {

async function handlePostInit(
init: InitEntities,
caches: Awaited<ReturnType<typeof loadUserCachedEntities>>
caches: Awaited<ReturnType<typeof loadUserCachedEntities>>,
guest: boolean
) {
if (init.allChars) {
getStore('character').loadImpersonate()
}

await Promise.all([
caches?.presets ? getStore('presets').getPresets() : Promise.resolve(),
caches?.books ? await getStore('memory').getAll() : Promise.resolve(),
caches?.presets || guest ? getStore('presets').getPresets() : Promise.resolve(),
caches?.books || guest ? await getStore('memory').getAll() : Promise.resolve(),
getStore('character').getAllChats(true),
])

if (!init.allChars) {
if (!init.allChars || guest) {
getStore('character').loadImpersonate()
}
}
Expand Down