Skip to content

Commit

Permalink
Merge pull request ShipBit#39 from ShipBit/1-editable-messages--chat-…
Browse files Browse the repository at this point in the history
…branching

Editable messages & chat branching
  • Loading branch information
Shackless authored Apr 12, 2023
2 parents e1ecaae + e749a9f commit 717efc5
Show file tree
Hide file tree
Showing 22 changed files with 791 additions and 231 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@

Sorry folks, no semantic versioning, proper tagging or fancy automations yet. I'm just going to keep an old-sql manual changelog here for now.

## April 12, 2023

- **Messages are now editable**. This creates a branch in the chat history and preserves your old prompts and completions. You can continue writing in any branch, just like you are used to from the OpenAI client. This change requires a (in-place, client-side) migration of the chat data structure, so you might have to wait a few seconds for each chat to load for the first time after the update.

## April 05, 2023

- Suggest Title button now shows a loading spinner and is disabled while loading
Expand Down
12 changes: 7 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,8 @@ SlickGPT is a light-weight "use-your-own-API-key" web client for the OpenAI API
- **Fancy User Interface** <br> Interact with an elegant and cleanUI that makes chatting fun and explains a lot of the heavy stuff to users.
- **Mobile first and fully responsive** <br> SlickGPT is always at your hand. Literally, on your phone.
- **Local History** <br> Your chat history is stored in localStorage and never leaves your machine (until you actively decide to share chats).
- **Delete and edit messages** <br> Just like you are used to from the OpenAI client.
- **Auto-suggest chat titles** <br> SlickGPT can suggest a title for your chat based on the first message you send.
- **Share Chats** <br> Generate shareable links for your chats with 3 clicks to collaborate and brainstorm ideas with your team or friends. Without any authentication.
- **Set Context** <br> Provide your own context to guide the AI model while giving responses, ensuring relevant and focused outcomes.
- **Cost Calculation** <br> Keep track of and control your API usage costs with an in-built token cost calculator for your chats.
Expand All @@ -67,7 +69,7 @@ SlickGPT is a light-weight "use-your-own-API-key" web client for the OpenAI API
- **Use your own API Key** <br> Keep your API calls private and secure by using your own OpenAI API key.
- **Host Yourself / Run Everywhere** <br> Run the instance locally on your machine or host it on your preferred cloud provider.

See a **YouTube video** for more details:
See a **YouTube video** for more details:

[![YouTube video of SlickGPT](https://img.youtube.com/vi/rzpzKhe4v9s/0.jpg)](https://youtu.be/rzpzKhe4v9s)

Expand Down Expand Up @@ -135,15 +137,15 @@ While ChatGPT offers a great conversational AI experience, it lacks some feature
| Chat history |||
| Highlight / Format code |||
| Use Your Own API Key |||
| Edit and branch messages |||
| Stop generation |||
| Host Yourself / Run Locally |||
| Share Chats |||
| Set Context |||
| Change model configuration |||
| No Login Required |||
| Token Cost Calculation |||
| Mobile-first design |||
| Edit and branch messages |||
| Stop generation |||

As you can see, SlickGPT includes several additional features that cater to a broad range of user needs, such as hosting the service yourself, using a local chat history, sharing chats, and customizing the chat configurations. Moreover, SlickGPT does not require a login, allowing for faster and more streamlined access. These added functionalities make SlickGPT a more versatile and convenient solution for users seeking an advanced ChatGPT experience.

Expand All @@ -154,9 +156,9 @@ As you can see, SlickGPT includes several additional features that cater to a br
## Roadmap

- [x] Add light/dark mode switch
- [x] Editable messages and branching chat history
- [x] Stop completion generation
- [ ] Add theme switcher
- [ ] Editable messages and branching chat history
- [ ] Stop completion generation
- [ ] More documentation
- [ ] i18n
- [ ] English
Expand Down
33 changes: 30 additions & 3 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

42 changes: 22 additions & 20 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@shipbit/slickgpt",
"version": "1.1.1",
"version": "1.2.0",
"license": "MIT",
"author": {
"name": "Simon Hopstätter",
Expand All @@ -21,43 +21,45 @@
"format": "prettier --plugin-search-dir . --write ."
},
"devDependencies": {
"@skeletonlabs/skeleton": "^1.0.0",
"@sveltejs/adapter-vercel": "^2.3.1",
"@sveltejs/kit": "^1.11.0",
"@skeletonlabs/skeleton": "^1.1.0",
"@sveltejs/adapter-vercel": "^2.4.1",
"@sveltejs/kit": "^1.15.2",
"@tailwindcss/forms": "^0.5.3",
"@tailwindcss/typography": "^0.5.9",
"@types/common-tags": "^1.8.1",
"@typescript-eslint/eslint-plugin": "^5.54.1",
"@typescript-eslint/parser": "^5.54.1",
"@types/uuid": "^9.0.1",
"@typescript-eslint/eslint-plugin": "^5.58.0",
"@typescript-eslint/parser": "^5.58.0",
"autoprefixer": "^10.4.14",
"eslint": "^8.36.0",
"eslint-config-prettier": "^8.7.0",
"eslint": "^8.38.0",
"eslint-config-prettier": "^8.8.0",
"eslint-plugin-svelte3": "^4.0.0",
"postcss": "^8.4.21",
"prettier": "^2.8.4",
"prettier-plugin-svelte": "^2.9.0",
"svelte": "^3.56.0",
"svelte-check": "^3.1.2",
"svelte-preprocess": "^5.0.1",
"tailwindcss": "^3.2.7",
"prettier": "^2.8.7",
"prettier-plugin-svelte": "^2.10.0",
"svelte": "^3.58.0",
"svelte-check": "^3.2.0",
"svelte-preprocess": "^5.0.3",
"tailwindcss": "^3.3.1",
"tslib": "^2.5.0",
"typescript": "^4.9.5",
"vite": "^4.1.4"
"typescript": "^5.0.4",
"vite": "^4.2.1"
},
"type": "module",
"dependencies": {
"@floating-ui/dom": "^1.2.4",
"@floating-ui/dom": "^1.2.6",
"@inqling/svelte-icons": "^3.1.0",
"@tailwindcss/line-clamp": "^0.4.4",
"common-tags": "^1.8.2",
"firebase": "^9.17.2",
"firebase": "^9.19.1",
"gpt3-tokenizer": "^1.1.5",
"highlight.js": "^11.7.0",
"javascript-time-ago": "^2.5.9",
"openai": "^3.2.1",
"random-word-slugs": "^0.1.6",
"random-word-slugs": "^0.1.7",
"snarkdown": "^2.0.0",
"sse.js": "^0.6.1",
"svelte-legos": "^0.1.7"
"svelte-legos": "^0.2.1",
"uuid": "^9.0.0"
}
}
83 changes: 83 additions & 0 deletions src/lib/Chat.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
<script lang="ts">
import type { Chat } from '$misc/shared';
import { onDestroy } from 'svelte';
import { ProgressRadial } from '@skeletonlabs/skeleton';
import snarkdown from 'snarkdown';
import { chatStore, isLoadingAnswerStore, liveAnswerStore } from '$misc/stores';
import { scrollIntoView } from '$misc/actions';
import ChatMessages from './ChatMessages.svelte';
export let slug: string;
export let chat: Chat | undefined = undefined;
let anchor: HTMLElement;
$: if ($chatStore[slug]) {
// If this is used in the "Shared chat" view, the chat is not in the local store.
// Instead it's loaded from the db and passed in as a prop.
chat = $chatStore[slug];
}
const unsubscribe = liveAnswerStore.subscribe((answer) => {
if (answer.content) {
scrollIntoView(anchor);
}
});
onDestroy(unsubscribe);
</script>

{#if chat}
<div
id="chat"
class="flex flex-col container h-full mx-auto px-4 md:px-8"
style="justify-content: end"
>
<slot name="additional-content-top" />

<div class="flex flex-col max-w-4xl md:mx-auto space-y-6 pt-6">
<!-- Message history -->
<ChatMessages {slug} siblings={chat.messages} on:editMessage />

<!-- Live Message -->
{#if $isLoadingAnswerStore}
<div class="place-self-start">
<div class="p-5 rounded-2xl variant-ghost-tertiary rounded-tl-none">
{@html snarkdown($liveAnswerStore.content)}
</div>
</div>
{/if}
</div>

<slot name="additional-content-bottom" />

<!-- Progress indicator -->
<div
class="animate-pulse md:w-12 self-center py-2 md:py-6"
class:invisible={!$isLoadingAnswerStore}
>
<ProgressRadial
class="w-8"
stroke={120}
meter="stroke-tertiary-500"
track="stroke-tertiary-500/30"
/>
</div>

<!-- element is used to scroll to the bottom of the page -->
<!-- the Svelte action lets the view autoscroll to bottom initially as soon as the anchor is rendered -->
<div id="anchor" use:scrollIntoView bind:this={anchor} />
</div>
{/if}

<style>
/* stay at the bottom of the page when messages are added */
#chat * {
overflow-anchor: none;
}
#anchor {
overflow-anchor: auto;
height: 1px;
}
</style>
Loading

0 comments on commit 717efc5

Please sign in to comment.