Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Menu
Open sidebar
chenpangpang
open-webui
Commits
987685db
Commit
987685db
authored
Jan 18, 2024
by
Timothy J. Baek
Browse files
feat: convo tagging full integration
parent
d5ed1196
Changes
5
Show whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
184 additions
and
118 deletions
+184
-118
backend/apps/web/models/tags.py
backend/apps/web/models/tags.py
+35
-20
backend/apps/web/routers/chats.py
backend/apps/web/routers/chats.py
+16
-6
src/lib/components/layout/Navbar.svelte
src/lib/components/layout/Navbar.svelte
+77
-89
src/routes/(app)/+page.svelte
src/routes/(app)/+page.svelte
+26
-2
src/routes/(app)/c/[id]/+page.svelte
src/routes/(app)/c/[id]/+page.svelte
+30
-1
No files found.
backend/apps/web/models/tags.py
View file @
987685db
...
...
@@ -15,7 +15,8 @@ from apps.web.internal.db import DB
class
Tag
(
Model
):
name
=
CharField
(
unique
=
True
)
id
=
CharField
(
unique
=
True
)
name
=
CharField
()
user_id
=
CharField
()
data
=
TextField
(
null
=
True
)
...
...
@@ -24,7 +25,8 @@ class Tag(Model):
class
ChatIdTag
(
Model
):
tag_name
=
ForeignKeyField
(
Tag
,
backref
=
"chat_id_tags"
)
id
=
CharField
(
unique
=
True
)
tag_name
=
CharField
()
chat_id
=
CharField
()
user_id
=
CharField
()
timestamp
=
DateField
()
...
...
@@ -34,12 +36,14 @@ class ChatIdTag(Model):
class
TagModel
(
BaseModel
):
id
:
str
name
:
str
user_id
:
str
data
:
Optional
[
str
]
=
None
class
ChatIdTagModel
(
BaseModel
):
id
:
str
tag_name
:
str
chat_id
:
str
user_id
:
str
...
...
@@ -70,14 +74,15 @@ class TagTable:
db
.
create_tables
([
Tag
,
ChatIdTag
])
def
insert_new_tag
(
self
,
name
:
str
,
user_id
:
str
)
->
Optional
[
TagModel
]:
tag
=
TagModel
(
**
{
"user_id"
:
user_id
,
"name"
:
name
})
id
=
str
(
uuid
.
uuid4
())
tag
=
TagModel
(
**
{
"id"
:
id
,
"user_id"
:
user_id
,
"name"
:
name
})
try
:
result
=
Tag
.
create
(
**
tag
.
model_dump
())
if
result
:
return
tag
else
:
return
None
except
:
except
Exception
as
e
:
return
None
def
get_tag_by_name_and_user_id
(
...
...
@@ -86,17 +91,27 @@ class TagTable:
try
:
tag
=
Tag
.
get
(
Tag
.
name
==
name
,
Tag
.
user_id
==
user_id
)
return
TagModel
(
**
model_to_dict
(
tag
))
except
:
except
Exception
as
e
:
return
None
def
add_tag_to_chat
(
self
,
user_id
:
str
,
form_data
:
ChatIdTagForm
)
->
Optional
[
ChatTag
sResponse
]:
)
->
Optional
[
Chat
Id
Tag
Model
]:
tag
=
self
.
get_tag_by_name_and_user_id
(
form_data
.
tag_name
,
user_id
)
if
tag
==
None
:
tag
=
self
.
insert_new_tag
(
form_data
.
tag_name
,
user_id
)
chatIdTag
=
ChatIdTagModel
(
**
{
"user_id"
:
user_id
,
"tag_name"
:
tag
.
name
})
print
(
tag
)
id
=
str
(
uuid
.
uuid4
())
chatIdTag
=
ChatIdTagModel
(
**
{
"id"
:
id
,
"user_id"
:
user_id
,
"chat_id"
:
form_data
.
chat_id
,
"tag_name"
:
tag
.
name
,
"timestamp"
:
int
(
time
.
time
()),
}
)
try
:
result
=
ChatIdTag
.
create
(
**
chatIdTag
.
model_dump
())
if
result
:
...
...
@@ -109,19 +124,17 @@ class TagTable:
def
get_tags_by_chat_id_and_user_id
(
self
,
chat_id
:
str
,
user_id
:
str
)
->
List
[
TagModel
]:
return
[
TagModel
(
**
model_to_dict
(
tag
))
for
tag
in
Tag
.
select
().
where
(
Tag
.
name
in
[
tag_names
=
[
ChatIdTagModel
(
**
model_to_dict
(
chat_id_tag
)).
tag_name
for
chat_id_tag
in
ChatIdTag
.
select
()
.
where
(
(
ChatIdTag
.
user_id
==
user_id
)
&
(
ChatIdTag
.
chat_id
==
chat_id
)
)
.
where
((
ChatIdTag
.
user_id
==
user_id
)
&
(
ChatIdTag
.
chat_id
==
chat_id
))
.
order_by
(
ChatIdTag
.
timestamp
.
desc
())
]
)
print
(
tag_names
)
return
[
TagModel
(
**
model_to_dict
(
tag
))
for
tag
in
Tag
.
select
().
where
(
Tag
.
name
.
in_
(
tag_names
))
]
def
get_chat_ids_by_tag_name_and_user_id
(
...
...
@@ -152,7 +165,8 @@ class TagTable:
&
(
ChatIdTag
.
chat_id
==
chat_id
)
&
(
ChatIdTag
.
user_id
==
user_id
)
)
query
.
execute
()
# Remove the rows, return number of rows removed.
res
=
query
.
execute
()
# Remove the rows, return number of rows removed.
print
(
res
)
tag_count
=
self
.
count_chat_ids_by_tag_name_and_user_id
(
tag_name
,
user_id
)
if
tag_count
==
0
:
...
...
@@ -163,7 +177,8 @@ class TagTable:
query
.
execute
()
# Remove the rows, return number of rows removed.
return
True
except
:
except
Exception
as
e
:
print
(
"delete_tag"
,
e
)
return
False
def
delete_tags_by_chat_id_and_user_id
(
self
,
chat_id
:
str
,
user_id
:
str
)
->
bool
:
...
...
backend/apps/web/routers/chats.py
View file @
987685db
...
...
@@ -19,6 +19,7 @@ from apps.web.models.chats import (
from
apps.web.models.tags
import
(
TagModel
,
ChatIdTagModel
,
ChatIdTagForm
,
ChatTagsResponse
,
Tags
,
...
...
@@ -132,7 +133,8 @@ async def delete_chat_by_id(id: str, user=Depends(get_current_user)):
async
def
get_chat_tags_by_id
(
id
:
str
,
user
=
Depends
(
get_current_user
)):
tags
=
Tags
.
get_tags_by_chat_id_and_user_id
(
id
,
user
.
id
)
if
tags
:
if
tags
!=
None
:
print
(
tags
)
return
tags
else
:
raise
HTTPException
(
...
...
@@ -145,17 +147,25 @@ async def get_chat_tags_by_id(id: str, user=Depends(get_current_user)):
############################
@
router
.
post
(
"/{id}/tags"
,
response_model
=
Optional
[
ChatTag
sResponse
])
@
router
.
post
(
"/{id}/tags"
,
response_model
=
Optional
[
Chat
Id
Tag
Model
])
async
def
add_chat_tag_by_id
(
id
:
str
,
form_data
:
ChatIdTagForm
,
user
=
Depends
(
get_current_user
)
):
tag
=
Tags
.
add_tag_to_chat
(
user
.
id
,
{
"tag_name"
:
form_data
.
tag_name
,
"chat_id"
:
id
})
tags
=
Tags
.
get_tags_by_chat_id_and_user_id
(
id
,
user
.
id
)
if
form_data
.
tag_name
not
in
tags
:
tag
=
Tags
.
add_tag_to_chat
(
user
.
id
,
form_data
)
if
tag
:
return
tag
else
:
raise
HTTPException
(
status_code
=
status
.
HTTP_401_UNAUTHORIZED
,
detail
=
ERROR_MESSAGES
.
NOT_FOUND
status_code
=
status
.
HTTP_401_UNAUTHORIZED
,
detail
=
ERROR_MESSAGES
.
NOT_FOUND
,
)
else
:
raise
HTTPException
(
status_code
=
status
.
HTTP_401_UNAUTHORIZED
,
detail
=
ERROR_MESSAGES
.
DEFAULT
()
)
...
...
src/lib/components/layout/Navbar.svelte
View file @
987685db
...
...
@@ -12,22 +12,11 @@
export let title: string = 'Ollama Web UI';
export let shareEnabled: boolean = false;
let showShareChatModal = false;
export let tags = [];
export let addTag: Function;
export let deleteTag: Function;
let tags = [
// {
// name: 'general'
// },
// {
// name: 'medicine'
// },
// {
// name: 'cooking'
// },
// {
// name: 'education'
// }
];
let showShareChatModal = false;
let tagName = '';
let showTagInput = false;
...
...
@@ -74,16 +63,17 @@
saveAs(blob, `chat-${chat.title}.txt`);
};
const addTag = () => {
if (!tags.find((e) => e.name === tagName)) {
tags = [
...tags,
{
name: JSON.parse(JSON.stringify(tagName))
}
];
}
const addTag
Handler
= () => {
//
if (!tags.find((e) => e.name === tagName)) {
//
tags = [
//
...tags,
//
{
//
name: JSON.parse(JSON.stringify(tagName))
//
}
//
];
//
}
addTag(tagName);
tagName = '';
showTagInput = false;
};
...
...
@@ -126,6 +116,7 @@
</div>
<div class="pl-2 self-center flex items-center space-x-2">
{#if shareEnabled}
<div class="flex flex-row space-x-0.5 line-clamp-1">
{#each tags as tag}
<div
...
...
@@ -137,9 +128,7 @@
<button
class=" m-auto self-center cursor-pointer"
on:click={() => {
console.log(tag.name);
tags = tags.filter((t) => t.name !== tag.name);
deleteTag(tag.name);
}}
>
<svg
...
...
@@ -167,7 +156,7 @@
<button
on:click={() => {
addTag();
addTag
Handler
();
}}
>
<svg
...
...
@@ -210,7 +199,6 @@
</div>
</div>
{#if shareEnabled}
<button
class=" cursor-pointer p-1.5 flex dark:hover:bg-gray-700 rounded-lg transition border dark:border-gray-600"
on:click={async () => {
...
...
src/routes/(app)/+page.svelte
View file @
987685db
...
...
@@ -10,7 +10,14 @@
import { copyToClipboard, splitStream } from '$lib/utils';
import { generateChatCompletion, cancelChatCompletion, generateTitle } from '$lib/apis/ollama';
import { createNewChat, getChatList, updateChatById } from '$lib/apis/chats';
import {
addTagById,
createNewChat,
deleteTagById,
getChatList,
getTagsById,
updateChatById
} from '$lib/apis/chats';
import { queryVectorDB } from '$lib/apis/rag';
import { generateOpenAIChatCompletion } from '$lib/apis/openai';
...
...
@@ -47,6 +54,7 @@
}, {});
let chat = null;
let tags = [];
let title = '';
let prompt = '';
...
...
@@ -673,6 +681,22 @@
}
};
const getTags = async () => {
return await getTagsById(localStorage.token, $chatId).catch(async (error) => {
return [];
});
};
const addTag = async (tagName) => {
const res = await addTagById(localStorage.token, $chatId, tagName);
tags = await getTags();
};
const deleteTag = async (tagName) => {
const res = await deleteTagById(localStorage.token, $chatId, tagName);
tags = await getTags();
};
const setChatTitle = async (_chatId, _title) => {
if (_chatId === $chatId) {
title = _title;
...
...
@@ -691,7 +715,7 @@
}}
/>
<Navbar {title} shareEnabled={messages.length > 0} {initNewChat} />
<Navbar {title} shareEnabled={messages.length > 0} {initNewChat}
{tags} {addTag} {deleteTag}
/>
<div class="min-h-screen w-full flex justify-center">
<div class=" py-2.5 flex flex-col justify-between w-full">
<div class="max-w-2xl mx-auto w-full px-3 md:px-0 mt-10">
...
...
src/routes/(app)/c/[id]/+page.svelte
View file @
987685db
...
...
@@ -10,7 +10,15 @@
import { copyToClipboard, splitStream, convertMessagesToHistory } from '$lib/utils';
import { generateChatCompletion, generateTitle } from '$lib/apis/ollama';
import { createNewChat, getChatById, getChatList, updateChatById } from '$lib/apis/chats';
import {
addTagById,
createNewChat,
deleteTagById,
getChatById,
getChatList,
getTagsById,
updateChatById
} from '$lib/apis/chats';
import { queryVectorDB } from '$lib/apis/rag';
import { generateOpenAIChatCompletion } from '$lib/apis/openai';
...
...
@@ -49,6 +57,7 @@
}, {});
let chat = null;
let tags = [];
let title = '';
let prompt = '';
...
...
@@ -97,6 +106,7 @@
});
if (chat) {
tags = await getTags();
const chatContent = chat.chat;
if (chatContent) {
...
...
@@ -688,6 +698,22 @@
await chats.set(await getChatList(localStorage.token));
};
const getTags = async () => {
return await getTagsById(localStorage.token, $chatId).catch(async (error) => {
return [];
});
};
const addTag = async (tagName) => {
const res = await addTagById(localStorage.token, $chatId, tagName);
tags = await getTags();
};
const deleteTag = async (tagName) => {
const res = await deleteTagById(localStorage.token, $chatId, tagName);
tags = await getTags();
};
onMount(async () => {
if (!($settings.saveChatHistory ?? true)) {
await goto('/');
...
...
@@ -713,6 +739,9 @@
goto('/');
}}
{tags}
{addTag}
{deleteTag}
/>
<div class="min-h-screen w-full flex justify-center">
<div class=" py-2.5 flex flex-col justify-between w-full">
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment