Skip to content

Commit 04c6480

Browse files
authored
Merge pull request #5 from jumpserver/pr@main@keep_chat_model
perf: keep chat model
2 parents 8d74580 + eafb7ee commit 04c6480

88 files changed

Lines changed: 1340 additions & 946 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.github/workflows/build-release.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ name: Release
33
on:
44
push:
55
branches:
6-
- master # or whatever branch you want to use
6+
- main # or whatever branch you want to use
77

88
jobs:
99
release:

README.md

Lines changed: 192 additions & 65 deletions
Large diffs are not rendered by default.

backend/open_webui/config.py

Lines changed: 14 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -956,7 +956,7 @@ def feishu_oauth_register(oauth: OAuth):
956956
ENABLE_OLLAMA_API = PersistentConfig(
957957
"ENABLE_OLLAMA_API",
958958
"ollama.enable",
959-
os.environ.get("ENABLE_OLLAMA_API", "False").lower() == "true",
959+
os.environ.get("ENABLE_OLLAMA_API", "True").lower() == "true",
960960
)
961961

962962
OLLAMA_API_BASE_URL = os.environ.get(
@@ -1114,14 +1114,14 @@ def feishu_oauth_register(oauth: OAuth):
11141114
(
11151115
False
11161116
if not WEBUI_AUTH
1117-
else os.environ.get("ENABLE_SIGNUP", "False").lower() == "true"
1117+
else os.environ.get("ENABLE_SIGNUP", "True").lower() == "true"
11181118
),
11191119
)
11201120

11211121
ENABLE_LOGIN_FORM = PersistentConfig(
11221122
"ENABLE_LOGIN_FORM",
11231123
"ui.ENABLE_LOGIN_FORM",
1124-
os.environ.get("ENABLE_LOGIN_FORM", "False").lower() == "true",
1124+
os.environ.get("ENABLE_LOGIN_FORM", "True").lower() == "true",
11251125
)
11261126

11271127

@@ -1322,11 +1322,11 @@ def feishu_oauth_register(oauth: OAuth):
13221322
)
13231323

13241324
USER_PERMISSIONS_CHAT_TTS = (
1325-
os.environ.get("USER_PERMISSIONS_CHAT_TTS", "False").lower() == "true"
1325+
os.environ.get("USER_PERMISSIONS_CHAT_TTS", "True").lower() == "true"
13261326
)
13271327

13281328
USER_PERMISSIONS_CHAT_CALL = (
1329-
os.environ.get("USER_PERMISSIONS_CHAT_CALL", "False").lower() == "true"
1329+
os.environ.get("USER_PERMISSIONS_CHAT_CALL", "True").lower() == "true"
13301330
)
13311331

13321332
USER_PERMISSIONS_CHAT_MULTIPLE_MODELS = (
@@ -1426,13 +1426,13 @@ def feishu_oauth_register(oauth: OAuth):
14261426
ENABLE_NOTES = PersistentConfig(
14271427
"ENABLE_NOTES",
14281428
"notes.enable",
1429-
os.environ.get("ENABLE_NOTES", "False").lower() == "true",
1429+
os.environ.get("ENABLE_NOTES", "True").lower() == "true",
14301430
)
14311431

14321432
ENABLE_EVALUATION_ARENA_MODELS = PersistentConfig(
14331433
"ENABLE_EVALUATION_ARENA_MODELS",
14341434
"evaluation.arena.enable",
1435-
os.environ.get("ENABLE_EVALUATION_ARENA_MODELS", "False").lower() == "true",
1435+
os.environ.get("ENABLE_EVALUATION_ARENA_MODELS", "True").lower() == "true",
14361436
)
14371437
EVALUATION_ARENA_MODELS = PersistentConfig(
14381438
"EVALUATION_ARENA_MODELS",
@@ -1475,7 +1475,7 @@ def feishu_oauth_register(oauth: OAuth):
14751475
ENABLE_COMMUNITY_SHARING = PersistentConfig(
14761476
"ENABLE_COMMUNITY_SHARING",
14771477
"ui.enable_community_sharing",
1478-
os.environ.get("ENABLE_COMMUNITY_SHARING", "False").lower() == "true",
1478+
os.environ.get("ENABLE_COMMUNITY_SHARING", "True").lower() == "true",
14791479
)
14801480

14811481
ENABLE_MESSAGE_RATING = PersistentConfig(
@@ -1595,49 +1595,26 @@ class BannerModel(BaseModel):
15951595
"task.title.prompt_template",
15961596
os.environ.get("TITLE_GENERATION_PROMPT_TEMPLATE", ""),
15971597
)
1598-
# TODO: re-enable examples after testing
1599-
# DEFAULT_TITLE_GENERATION_PROMPT_TEMPLATE = """### Task:
1600-
# Generate a concise, 3-5 word title with an emoji summarizing the chat history.
1601-
# ### Guidelines:
1602-
# - The title should clearly represent the main theme or subject of the conversation.
1603-
# - Use emojis that enhance understanding of the topic, but avoid quotation marks or special formatting.
1604-
# - Write the title in the chat's primary language; default to English if multilingual.
1605-
# - Prioritize accuracy over excessive creativity; keep it clear and simple.
1606-
# - Your entire response must consist solely of the JSON object, without any introductory or concluding text.
1607-
# - The output must be a single, raw JSON object, without any markdown code fences or other encapsulating text.
1608-
# - Ensure no conversational text, affirmations, or explanations precede or follow the raw JSON output, as this will cause direct parsing failure.
1609-
# ### Output:
1610-
# JSON format: { "title": "your concise title here" }
1611-
# ### Examples:
1612-
# - { "title": "📉 Stock Market Trends" },
1613-
# - { "title": "🍪 Perfect Chocolate Chip Recipe" },
1614-
# - { "title": "Evolution of Music Streaming" },
1615-
# - { "title": "Remote Work Productivity Tips" },
1616-
# - { "title": "Artificial Intelligence in Healthcare" },
1617-
# - { "title": "🎮 Video Game Development Insights" }
1618-
# ### Chat History:
1619-
# <chat_history>
1620-
# {{MESSAGES:END:2}}
1621-
# </chat_history>"""
16221598

16231599
DEFAULT_TITLE_GENERATION_PROMPT_TEMPLATE = """### Task:
1624-
Generate a concise, 3-5 word title.
1600+
Generate a concise, 3-5 word title with an emoji summarizing the chat history.
16251601
### Guidelines:
16261602
- The title should clearly represent the main theme or subject of the conversation.
1627-
- Use the primary language of the chat to write the title; if the chat contains multiple languages, generate the title in the primary language used.
1603+
- Use emojis that enhance understanding of the topic, but avoid quotation marks or special formatting.
1604+
- Write the title in the chat's primary language; default to English if multilingual.
16281605
- Prioritize accuracy over excessive creativity; keep it clear and simple.
16291606
- Your entire response must consist solely of the JSON object, without any introductory or concluding text.
16301607
- The output must be a single, raw JSON object, without any markdown code fences or other encapsulating text.
16311608
- Ensure no conversational text, affirmations, or explanations precede or follow the raw JSON output, as this will cause direct parsing failure.
16321609
### Output:
16331610
JSON format: { "title": "your concise title here" }
16341611
### Examples:
1635-
- { "title": "Stock Market Trends" },
1636-
- { "title": "Perfect Chocolate Chip Recipe" },
1612+
- { "title": "📉 Stock Market Trends" },
1613+
- { "title": "🍪 Perfect Chocolate Chip Recipe" },
16371614
- { "title": "Evolution of Music Streaming" },
16381615
- { "title": "Remote Work Productivity Tips" },
16391616
- { "title": "Artificial Intelligence in Healthcare" },
1640-
- { "title": "Video Game Development Insights" }
1617+
- { "title": "🎮 Video Game Development Insights" }
16411618
### Chat History:
16421619
<chat_history>
16431620
{{MESSAGES:END:2}}

backend/open_webui/env.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,7 @@
111111

112112
log.setLevel(SRC_LOG_LEVELS["CONFIG"])
113113

114-
WEBUI_NAME = os.environ.get("WEBUI_NAME", "JumpServer Chat AI &")
114+
WEBUI_NAME = os.environ.get("WEBUI_NAME", "Open WebUI")
115115
if WEBUI_NAME != "Open WebUI":
116116
WEBUI_NAME += " (Open WebUI)"
117117

backend/open_webui/jms/chat.py

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -18,25 +18,25 @@ class ChatHandler(BaseWisp):
1818
def list(self, query: Optional[Dict[str, Any]] = None) -> List[dict]:
1919
query = self._normalize_query(query)
2020
resp = self._request("GET", CHAT_URL, query=query, action="list chats")
21-
return self._loads(CHAT_URL, resp.body)
21+
return self._loads(resp.body)
2222

2323
def retrieve(self, chat_id: str) -> dict:
2424
self._ensure_id(chat_id)
2525
path = f"{CHAT_URL}{chat_id}/"
2626
resp = self._request("GET", path, action=f"retrieve chat {chat_id}")
27-
return self._loads(path, resp.body)
27+
return self._loads(resp.body)
2828

2929
def create(self, data: Dict[str, Any]) -> dict:
3030
body = self._dumps(data)
3131
resp = self._request("POST", CHAT_URL, body=body, action="create chat")
32-
return self._loads(CHAT_URL, resp.body)
32+
return self._loads(resp.body)
3333

3434
def update(self, chat_id: Optional[str] = None, data: Dict[str, Any] = None, query: Dict[str, Any] = None) -> dict:
3535
self._ensure_id(chat_id)
3636
path = f"{CHAT_URL}{chat_id}/"
3737
body = self._dumps(data)
3838
resp = self._request("PATCH", path, query=query, body=body, action=f"update chat {chat_id}")
39-
return self._loads(path, resp.body)
39+
return self._loads(resp.body)
4040

4141
def destroy(self, chat_id: Optional[str] = None, query: Dict[str, Any] = None) -> None:
4242
"""
@@ -100,11 +100,11 @@ def _dumps(data: Dict[str, Any]) -> bytes:
100100
raise WispError(f"Failed to serialize request body: {e}") from e
101101

102102
@staticmethod
103-
def _loads(path: str, b: bytes) -> Any:
103+
def _loads(b: bytes) -> Any:
104104
try:
105105
return json.loads(b.decode("utf-8")) if b else None
106106
except (UnicodeDecodeError, json.JSONDecodeError) as e:
107-
raise WispError(f"Failed to parse response body: {e} path {path}") from e
107+
raise WispError(f"Failed to parse response body: {e}") from e
108108

109109
@staticmethod
110110
def _safe_decode(b: Optional[bytes]) -> str:

backend/open_webui/models/chats.py

Lines changed: 21 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -114,7 +114,6 @@ class ChatResponse(BaseModel):
114114
archived: bool
115115
pinned: Optional[bool] = False
116116
meta: dict = {}
117-
session_info: dict = {}
118117
folder_id: Optional[str] = None
119118

120119

@@ -151,7 +150,7 @@ def insert_new_chat(self, form_data: ChatForm, sid: str, request: Request, user:
151150
'title': form_data.chat['title'] if 'title' in form_data.chat else 'New Chat',
152151
'chat': form_data.chat,
153152
'socket_id': sid,
154-
'folder_id': form_data.folder_id or '',
153+
'folder_id': form_data.folder_id,
155154
'session_info': {
156155
'org_id': session.org_id,
157156
'asset': session.asset,
@@ -195,7 +194,7 @@ def import_chat(
195194
}
196195
)
197196

198-
result = Chat(**chat)
197+
result = Chat(**chat.model_dump())
199198
db.add(result)
200199
db.commit()
201200
db.refresh(result)
@@ -231,7 +230,7 @@ def update_chat_tags_by_id(
231230

232231
self.delete_all_tags_by_id_and_user_id(id, user.id)
233232

234-
for tag in chat['meta'].get("tags", []):
233+
for tag in chat.meta.get("tags", []):
235234
if self.count_chats_by_tag_name_and_user_id(tag, user.id) == 0:
236235
Tags.delete_tag_by_name_and_user_id(tag, user.id)
237236

@@ -316,19 +315,19 @@ def insert_shared_chat_by_chat_id(self, chat_id: str) -> Optional[ChatModel]:
316315
# Get the existing chat to share
317316
chat = db.get(Chat, chat_id)
318317
# Check if the chat is already shared
319-
if chat['share_id']:
320-
return self.get_chat_by_id_and_user_id(chat['share_id'], "shared")
318+
if chat.share_id:
319+
return self.get_chat_by_id_and_user_id(chat.share_id, "shared")
321320
# Create a new chat with the same data, but with a new ID
322321
shared_chat = ChatModel(
323322
**{
324323
"id": str(uuid.uuid4()),
325324
"user_id": f"shared-{chat_id}",
326-
"title": chat['title'],
327-
"chat": chat['chat'],
328-
"meta": chat['meta'],
329-
"pinned": chat['pinned'],
330-
"folder_id": chat['folder_id'],
331-
"created_at": chat['created_at'],
325+
"title": chat.title,
326+
"chat": chat.chat,
327+
"meta": chat.meta,
328+
"pinned": chat.pinned,
329+
"folder_id": chat.folder_id,
330+
"created_at": chat.created_at,
332331
"updated_at": int(time.time()),
333332
}
334333
)
@@ -358,11 +357,11 @@ def update_shared_chat_by_chat_id(self, chat_id: str) -> Optional[ChatModel]:
358357
if shared_chat is None:
359358
return self.insert_shared_chat_by_chat_id(chat_id)
360359

361-
shared_chat.title = chat['title']
362-
shared_chat.chat = chat['chat']
363-
shared_chat.meta = chat['meta']
364-
shared_chat.pinned = chat['pinned']
365-
shared_chat.folder_id = chat['folder_id']
360+
shared_chat.title = chat.title
361+
shared_chat.chat = chat.chat
362+
shared_chat.meta = chat.meta
363+
shared_chat.pinned = chat.pinned
364+
shared_chat.folder_id = chat.folder_id
366365
shared_chat.updated_at = int(time.time())
367366
db.commit()
368367
db.refresh(shared_chat)
@@ -703,7 +702,7 @@ def update_chat_folder_id_by_id_and_user_id(
703702
def get_chat_tags_by_id_and_user_id(self, id: str, user_id: str) -> list[TagModel]:
704703
with get_db() as db:
705704
chat = db.get(Chat, id)
706-
tags = chat['meta'].get("tags", [])
705+
tags = chat.meta.get("tags", [])
707706
return [Tags.get_tag_by_name_and_user_id(tag, user_id) for tag in tags]
708707

709708
# TODO
@@ -750,10 +749,10 @@ def add_chat_tag_by_id_and_user_id_and_tag_name(
750749
chat = db.get(Chat, _id)
751750

752751
tag_id = tag.id
753-
if tag_id not in chat['meta'].get("tags", []):
752+
if tag_id not in chat.meta.get("tags", []):
754753
chat.meta = {
755-
**chat['meta'],
756-
"tags": list(set(chat['meta'].get("tags", []) + [tag_id])),
754+
**chat.meta,
755+
"tags": list(set(chat.meta.get("tags", []) + [tag_id])),
757756
}
758757

759758
db.commit()
@@ -883,7 +882,7 @@ def delete_shared_chats_by_user_id(self, user_id: str) -> bool:
883882
try:
884883
with get_db() as db:
885884
chats_by_user = db.query(Chat).filter_by(user_id=user_id).all()
886-
shared_chat_ids = [f"shared-{chat['id']}" for chat in chats_by_user]
885+
shared_chat_ids = [f"shared-{chat.id}" for chat in chats_by_user]
887886

888887
db.query(Chat).filter(Chat.user_id.in_(shared_chat_ids)).delete()
889888
db.commit()

backend/open_webui/retrieval/models/external.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -49,8 +49,8 @@ def predict(
4949
{
5050
"X-OpenWebUI-User-Name": quote(user.name, safe=" "),
5151
"X-OpenWebUI-User-Id": user.id,
52-
"X-OpenWebUI-User-Username": user.username,
53-
"X-OpenWebUI-User-Role": 'admin',
52+
"X-OpenWebUI-User-Email": user.email,
53+
"X-OpenWebUI-User-Role": user.role,
5454
}
5555
if ENABLE_FORWARD_USER_INFO_HEADERS and user
5656
else {}

backend/open_webui/retrieval/utils.py

Lines changed: 10 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -595,9 +595,9 @@ def get_sources_from_items(
595595
# Chat Attached
596596
chat = Chats.get_chat_by_id(item.get("id"))
597597

598-
if chat and (user.role == "admin" or chat['user_id'] == user.id):
599-
messages_map = chat['chat'].get("history", {}).get("messages", {})
600-
message_id = chat['chat'].get("history", {}).get("currentId")
598+
if chat and (user.role == "admin" or chat.user_id == user.id):
599+
messages_map = chat.chat.get("history", {}).get("messages", {})
600+
message_id = chat.chat.get("history", {}).get("currentId")
601601

602602
if messages_map and message_id:
603603
# Reconstruct the message list in order
@@ -612,7 +612,7 @@ def get_sources_from_items(
612612
# User has access to the chat
613613
query_result = {
614614
"documents": [[message_history]],
615-
"metadatas": [[{"file_id": chat['id'], "name": chat['title']}]],
615+
"metadatas": [[{"file_id": chat.id, "name": chat.title}]],
616616
}
617617

618618
elif item.get("type") == "url":
@@ -797,7 +797,6 @@ def get_sources_from_items(
797797

798798
def get_model_path(model: str, update_model: bool = False):
799799
# Construct huggingface_hub kwargs with local_files_only to return the snapshot path
800-
return
801800
cache_dir = os.getenv("SENTENCE_TRANSFORMERS_HOME")
802801

803802
local_files_only = not update_model
@@ -862,8 +861,8 @@ def generate_openai_batch_embeddings(
862861
{
863862
"X-OpenWebUI-User-Name": quote(user.name, safe=" "),
864863
"X-OpenWebUI-User-Id": user.id,
865-
"X-OpenWebUI-User-Username": user.username,
866-
"X-OpenWebUI-User-Role": 'admin',
864+
"X-OpenWebUI-User-Email": user.email,
865+
"X-OpenWebUI-User-Role": user.role,
867866
}
868867
if ENABLE_FORWARD_USER_INFO_HEADERS and user
869868
else {}
@@ -911,8 +910,8 @@ def generate_azure_openai_batch_embeddings(
911910
{
912911
"X-OpenWebUI-User-Name": quote(user.name, safe=" "),
913912
"X-OpenWebUI-User-Id": user.id,
914-
"X-OpenWebUI-User-Username": user.username,
915-
"X-OpenWebUI-User-Role": 'admin',
913+
"X-OpenWebUI-User-Email": user.email,
914+
"X-OpenWebUI-User-Role": user.role,
916915
}
917916
if ENABLE_FORWARD_USER_INFO_HEADERS and user
918917
else {}
@@ -961,8 +960,8 @@ def generate_ollama_batch_embeddings(
961960
{
962961
"X-OpenWebUI-User-Name": quote(user.name, safe=" "),
963962
"X-OpenWebUI-User-Id": user.id,
964-
"X-OpenWebUI-User-Username": user.username,
965-
"X-OpenWebUI-User-Role": 'admin',
963+
"X-OpenWebUI-User-Email": user.email,
964+
"X-OpenWebUI-User-Role": user.role,
966965
}
967966
if ENABLE_FORWARD_USER_INFO_HEADERS
968967
else {}

backend/open_webui/routers/audio.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -374,8 +374,8 @@ async def speech(request: Request, user=Depends(get_verified_user)):
374374
{
375375
"X-OpenWebUI-User-Name": quote(user.name, safe=" "),
376376
"X-OpenWebUI-User-Id": user.id,
377-
"X-OpenWebUI-User-Username": user.username,
378-
"X-OpenWebUI-User-Role": 'admin',
377+
"X-OpenWebUI-User-Email": user.email,
378+
"X-OpenWebUI-User-Role": user.role,
379379
}
380380
if ENABLE_FORWARD_USER_INFO_HEADERS
381381
else {}

0 commit comments

Comments
 (0)