enh: knowledge author info

This commit is contained in:
Timothy Jaeryang Baek 2024-11-18 05:51:01 -08:00
parent a2a25fb571
commit 6c3e6710ef
5 changed files with 44 additions and 23 deletions

View File

@ -8,6 +8,7 @@ from open_webui.apps.webui.internal.db import Base, get_db
from open_webui.env import SRC_LOG_LEVELS from open_webui.env import SRC_LOG_LEVELS
from open_webui.apps.webui.models.files import FileMetadataResponse from open_webui.apps.webui.models.files import FileMetadataResponse
from open_webui.apps.webui.models.users import Users, UserResponse
from pydantic import BaseModel, ConfigDict from pydantic import BaseModel, ConfigDict
@ -79,17 +80,15 @@ class KnowledgeModel(BaseModel):
#################### ####################
class KnowledgeResponse(BaseModel): class KnowledgeUserModel(KnowledgeModel):
id: str user: Optional[UserResponse] = None
name: str
description: str
data: Optional[dict] = None
meta: Optional[dict] = None
access_control: Optional[dict] = None
created_at: int # timestamp in epoch
updated_at: int # timestamp in epoch
class KnowledgeResponse(KnowledgeModel):
files: Optional[list[FileMetadataResponse | dict]] = None
class KnowledgeUserResponse(KnowledgeUserModel):
files: Optional[list[FileMetadataResponse | dict]] = None files: Optional[list[FileMetadataResponse | dict]] = None
@ -127,10 +126,15 @@ class KnowledgeTable:
except Exception: except Exception:
return None return None
def get_knowledge_bases(self) -> list[KnowledgeModel]: def get_knowledge_bases(self) -> list[KnowledgeUserModel]:
with get_db() as db: with get_db() as db:
return [ return [
KnowledgeModel.model_validate(knowledge) KnowledgeUserModel.model_validate(
{
**KnowledgeModel.model_validate(knowledge).model_dump(),
"user": Users.get_user_by_id(knowledge.user_id).model_dump(),
}
)
for knowledge in db.query(Knowledge) for knowledge in db.query(Knowledge)
.order_by(Knowledge.updated_at.desc()) .order_by(Knowledge.updated_at.desc())
.all() .all()
@ -138,7 +142,7 @@ class KnowledgeTable:
def get_knowledge_bases_by_user_id( def get_knowledge_bases_by_user_id(
self, user_id: str, permission: str = "write" self, user_id: str, permission: str = "write"
) -> list[KnowledgeModel]: ) -> list[KnowledgeUserModel]:
knowledge_bases = self.get_knowledge_bases() knowledge_bases = self.get_knowledge_bases()
return [ return [
knowledge_base knowledge_base

View File

@ -8,6 +8,7 @@ from open_webui.apps.webui.models.knowledge import (
Knowledges, Knowledges,
KnowledgeForm, KnowledgeForm,
KnowledgeResponse, KnowledgeResponse,
KnowledgeUserResponse,
) )
from open_webui.apps.webui.models.files import Files, FileModel from open_webui.apps.webui.models.files import Files, FileModel
from open_webui.apps.retrieval.vector.connector import VECTOR_DB_CLIENT from open_webui.apps.retrieval.vector.connector import VECTOR_DB_CLIENT
@ -32,7 +33,7 @@ router = APIRouter()
############################ ############################
@router.get("/", response_model=list[KnowledgeResponse]) @router.get("/", response_model=list[KnowledgeUserResponse])
async def get_knowledge(user=Depends(get_verified_user)): async def get_knowledge(user=Depends(get_verified_user)):
knowledge_bases = [] knowledge_bases = []
@ -77,7 +78,7 @@ async def get_knowledge(user=Depends(get_verified_user)):
return knowledge_bases return knowledge_bases
@router.get("/list", response_model=list[KnowledgeResponse]) @router.get("/list", response_model=list[KnowledgeUserResponse])
async def get_knowledge_list(user=Depends(get_verified_user)): async def get_knowledge_list(user=Depends(get_verified_user)):
knowledge_bases = [] knowledge_bases = []

View File

@ -24,6 +24,8 @@
import Search from '../icons/Search.svelte'; import Search from '../icons/Search.svelte';
import Plus from '../icons/Plus.svelte'; import Plus from '../icons/Plus.svelte';
import Spinner from '../common/Spinner.svelte'; import Spinner from '../common/Spinner.svelte';
import { capitalizeFirstLetter } from '$lib/utils';
import Tooltip from '../common/Tooltip.svelte';
let loaded = false; let loaded = false;
@ -137,7 +139,11 @@
> >
<div class=" w-full"> <div class=" w-full">
<div class="flex items-center justify-between -mt-1"> <div class="flex items-center justify-between -mt-1">
<div class=" font-semibold line-clamp-1 h-fit">{item.name}</div> {#if item?.meta?.document}
<Badge type="muted" content={$i18n.t('Document')} />
{:else}
<Badge type="success" content={$i18n.t('Collection')} />
{/if}
<div class=" flex self-center"> <div class=" flex self-center">
<ItemMenu <ItemMenu
@ -150,17 +156,23 @@
</div> </div>
<div class=" self-center flex-1"> <div class=" self-center flex-1">
<div class=" font-semibold line-clamp-1 h-fit">{item.name}</div>
<div class=" text-xs overflow-hidden text-ellipsis line-clamp-1"> <div class=" text-xs overflow-hidden text-ellipsis line-clamp-1">
{item.description} {item.description}
</div> </div>
<div class="mt-5 flex justify-between"> <div class="mt-3 flex justify-between">
<div> <div class="text-xs">
{#if item?.meta?.document} <Tooltip
<Badge type="muted" content={$i18n.t('Document')} /> content={item?.user?.email}
{:else} className="flex shrink-0"
<Badge type="success" content={$i18n.t('Collection')} /> placement="top-start"
{/if} >
{$i18n.t('By {{name}}', {
name: capitalizeFirstLetter(item?.user?.name ?? item?.user?.email)
})}
</Tooltip>
</div> </div>
<div class=" text-xs text-gray-500 line-clamp-1"> <div class=" text-xs text-gray-500 line-clamp-1">
{$i18n.t('Updated')} {$i18n.t('Updated')}

View File

@ -32,6 +32,7 @@
import ChevronRight from '../icons/ChevronRight.svelte'; import ChevronRight from '../icons/ChevronRight.svelte';
import Switch from '../common/Switch.svelte'; import Switch from '../common/Switch.svelte';
import Spinner from '../common/Spinner.svelte'; import Spinner from '../common/Spinner.svelte';
import { capitalizeFirstLetter } from '$lib/utils';
let shiftKey = false; let shiftKey = false;
@ -288,7 +289,9 @@
<div class="flex gap-1 text-xs overflow-hidden"> <div class="flex gap-1 text-xs overflow-hidden">
<Tooltip content={model?.user?.email} className="flex shrink-0" placement="top-start"> <Tooltip content={model?.user?.email} className="flex shrink-0" placement="top-start">
<div class="shrink-0 text-gray-500"> <div class="shrink-0 text-gray-500">
By <span class=" capitalize">{model?.user?.name ?? model?.user?.email}</span> {$i18n.t('By {{name}}', {
name: capitalizeFirstLetter(model?.user?.name ?? model?.user?.email)
})}
</div> </div>
</Tooltip> </Tooltip>
</div> </div>

View File

@ -8,6 +8,7 @@ import { TTS_RESPONSE_SPLIT } from '$lib/types';
// Helper functions // Helper functions
////////////////////////// //////////////////////////
export const replaceTokens = (content, char, user) => { export const replaceTokens = (content, char, user) => {
const charToken = /{{char}}/gi; const charToken = /{{char}}/gi;
const userToken = /{{user}}/gi; const userToken = /{{user}}/gi;