Skip to content

Commit e9d6ada

Browse files
authored
Merge pull request open-webui#9445 from open-webui/dev
0.5.10
2 parents ab94468 + b8fe949 commit e9d6ada

File tree

10 files changed

+136
-68
lines changed

10 files changed

+136
-68
lines changed

CHANGELOG.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,14 @@ All notable changes to this project will be documented in this file.
55
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
66
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
77

8+
## [0.5.10] - 2025-02-05
9+
10+
### Fixed
11+
12+
- **⚙️ System Prompts Now Properly Templated via API**: Resolved an issue where system prompts were not being correctly processed when used through the API, ensuring template variables now function as expected.
13+
- **📝 '<thinking>' Tag Display Issue Fixed**: Fixed a bug where the 'thinking' tag was disrupting content rendering, ensuring clean and accurate text display.
14+
- **💻 Code Interpreter Stability with Custom Functions**: Addressed failures when using the Code Interpreter with certain custom functions like Anthropic, ensuring smoother execution and better compatibility.
15+
816
## [0.5.9] - 2025-02-05
917

1018
### Fixed

backend/open_webui/config.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1337,7 +1337,7 @@ class BannerModel(BaseModel):
13371337
- If the results are unclear, unexpected, or require validation, refine the code and execute it again as needed. Always aim to deliver meaningful insights from the results, iterating if necessary.
13381338
- If a link is provided for an image, audio, or any file, include it in the response exactly as given to ensure the user has access to the original resource.
13391339
- All responses should be communicated in the chat's primary language, ensuring seamless understanding. If the chat is multilingual, default to English for clarity.
1340-
- **If a link to an image, audio, or any file is provided in markdown format, explicitly display it as part of the response to ensure the user can access it easily, do NOT change the link.**
1340+
- **If a link to an image, audio, or any file is provided in markdown format, ALWAYS regurgitate explicitly display it as part of the response to ensure the user can access it easily, do NOT change the link.**
13411341
13421342
Ensure that the tools are effectively utilized to achieve the highest-quality analysis for the user."""
13431343

backend/open_webui/functions.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -250,7 +250,7 @@ def get_function_params(function_module, form_data, user, extra_params=None):
250250

251251
params = model_info.params.model_dump()
252252
form_data = apply_model_params_to_body_openai(params, form_data)
253-
form_data = apply_model_system_prompt_to_body(params, form_data, user)
253+
form_data = apply_model_system_prompt_to_body(params, form_data, metadata, user)
254254

255255
pipe_id = get_pipe_id(form_data)
256256
function_module = get_function_module_by_id(request, pipe_id)

backend/open_webui/routers/ollama.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1007,7 +1007,7 @@ async def generate_chat_completion(
10071007
payload["options"] = apply_model_params_to_body_ollama(
10081008
params, payload["options"]
10091009
)
1010-
payload = apply_model_system_prompt_to_body(params, payload, metadata)
1010+
payload = apply_model_system_prompt_to_body(params, payload, metadata, user)
10111011

10121012
# Check if user has access to the model
10131013
if not bypass_filter and user.role == "user":
@@ -1160,6 +1160,8 @@ async def generate_openai_chat_completion(
11601160
url_idx: Optional[int] = None,
11611161
user=Depends(get_verified_user),
11621162
):
1163+
metadata = form_data.pop("metadata", None)
1164+
11631165
try:
11641166
completion_form = OpenAIChatCompletionForm(**form_data)
11651167
except Exception as e:
@@ -1186,7 +1188,7 @@ async def generate_openai_chat_completion(
11861188

11871189
if params:
11881190
payload = apply_model_params_to_body_openai(params, payload)
1189-
payload = apply_model_system_prompt_to_body(params, payload, user)
1191+
payload = apply_model_system_prompt_to_body(params, payload, metadata, user)
11901192

11911193
# Check if user has access to the model
11921194
if user.role == "user":

backend/open_webui/routers/openai.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -566,7 +566,7 @@ async def generate_chat_completion(
566566

567567
params = model_info.params.model_dump()
568568
payload = apply_model_params_to_body_openai(params, payload)
569-
payload = apply_model_system_prompt_to_body(params, payload, metadata)
569+
payload = apply_model_system_prompt_to_body(params, payload, metadata, user)
570570

571571
# Check if user has access to the model
572572
if not bypass_filter and user.role == "user":

backend/open_webui/utils/middleware.py

Lines changed: 61 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1172,7 +1172,7 @@ def serialize_content_blocks(content_blocks, raw=False):
11721172

11731173
reasoning_duration = block.get("duration", None)
11741174

1175-
if reasoning_duration:
1175+
if reasoning_duration is not None:
11761176
if raw:
11771177
content = f'{content}\n<{block["tag"]}>{block["content"]}</{block["tag"]}>\n'
11781178
else:
@@ -1205,14 +1205,16 @@ def serialize_content_blocks(content_blocks, raw=False):
12051205
block_content = str(block["content"]).strip()
12061206
content = f"{content}{block['type']}: {block_content}\n"
12071207

1208-
return content
1208+
return content.strip()
12091209

12101210
def tag_content_handler(content_type, tags, content, content_blocks):
12111211
end_flag = False
12121212

12131213
def extract_attributes(tag_content):
12141214
"""Extract attributes from a tag if they exist."""
12151215
attributes = {}
1216+
if not tag_content: # Ensure tag_content is not None
1217+
return attributes
12161218
# Match attributes in the format: key="value" (ignores single quotes for simplicity)
12171219
matches = re.findall(r'(\w+)\s*=\s*"([^"]+)"', tag_content)
12181220
for key, value in matches:
@@ -1222,16 +1224,32 @@ def extract_attributes(tag_content):
12221224
if content_blocks[-1]["type"] == "text":
12231225
for tag in tags:
12241226
# Match start tag e.g., <tag> or <tag attr="value">
1225-
start_tag_pattern = rf"<{tag}(.*?)>"
1227+
start_tag_pattern = rf"<{tag}(\s.*?)?>"
12261228
match = re.search(start_tag_pattern, content)
12271229
if match:
1228-
# Extract attributes in the tag (if present)
1229-
attributes = extract_attributes(match.group(1))
1230+
attr_content = (
1231+
match.group(1) if match.group(1) else ""
1232+
) # Ensure it's not None
1233+
attributes = extract_attributes(
1234+
attr_content
1235+
) # Extract attributes safely
1236+
1237+
# Capture everything before and after the matched tag
1238+
before_tag = content[
1239+
: match.start()
1240+
] # Content before opening tag
1241+
after_tag = content[
1242+
match.end() :
1243+
] # Content after opening tag
1244+
12301245
# Remove the start tag from the currently handling text block
12311246
content_blocks[-1]["content"] = content_blocks[-1][
12321247
"content"
12331248
].replace(match.group(0), "")
12341249

1250+
if before_tag:
1251+
content_blocks[-1]["content"] = before_tag
1252+
12351253
if not content_blocks[-1]["content"]:
12361254
content_blocks.pop()
12371255

@@ -1245,12 +1263,17 @@ def extract_attributes(tag_content):
12451263
"started_at": time.time(),
12461264
}
12471265
)
1266+
1267+
if after_tag:
1268+
content_blocks[-1]["content"] = after_tag
1269+
12481270
break
12491271
elif content_blocks[-1]["type"] == content_type:
12501272
tag = content_blocks[-1]["tag"]
12511273
# Match end tag e.g., </tag>
12521274
end_tag_pattern = rf"</{tag}>"
12531275

1276+
# Check if the content has the end tag
12541277
if re.search(end_tag_pattern, content):
12551278
end_flag = True
12561279

@@ -1274,23 +1297,32 @@ def extract_attributes(tag_content):
12741297
split_content[1].strip() if len(split_content) > 1 else ""
12751298
)
12761299

1277-
print(f"block_content: {block_content}")
1278-
print(f"leftover_content: {leftover_content}")
1279-
12801300
if block_content:
12811301
content_blocks[-1]["content"] = block_content
12821302
content_blocks[-1]["ended_at"] = time.time()
12831303
content_blocks[-1]["duration"] = int(
12841304
content_blocks[-1]["ended_at"]
12851305
- content_blocks[-1]["started_at"]
12861306
)
1307+
12871308
# Reset the content_blocks by appending a new text block
1288-
content_blocks.append(
1289-
{
1290-
"type": "text",
1291-
"content": leftover_content,
1292-
}
1293-
)
1309+
if content_type != "code_interpreter":
1310+
if leftover_content:
1311+
1312+
content_blocks.append(
1313+
{
1314+
"type": "text",
1315+
"content": leftover_content,
1316+
}
1317+
)
1318+
else:
1319+
content_blocks.append(
1320+
{
1321+
"type": "text",
1322+
"content": "",
1323+
}
1324+
)
1325+
12941326
else:
12951327
# Remove the block if content is empty
12961328
content_blocks.pop()
@@ -1302,6 +1334,13 @@ def extract_attributes(tag_content):
13021334
"content": leftover_content,
13031335
}
13041336
)
1337+
else:
1338+
content_blocks.append(
1339+
{
1340+
"type": "text",
1341+
"content": "",
1342+
}
1343+
)
13051344

13061345
# Clean processed content
13071346
content = re.sub(
@@ -1332,7 +1371,14 @@ def extract_attributes(tag_content):
13321371
"code_interpreter", False
13331372
)
13341373

1335-
reasoning_tags = ["think", "reason", "reasoning", "thought", "Thought"]
1374+
reasoning_tags = [
1375+
"think",
1376+
"thinking",
1377+
"reason",
1378+
"reasoning",
1379+
"thought",
1380+
"Thought",
1381+
]
13361382
code_interpreter_tags = ["code_interpreter"]
13371383

13381384
try:

backend/open_webui/utils/payload.py

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
from open_webui.utils.task import prompt_variables_template
1+
from open_webui.utils.task import prompt_template, prompt_variables_template
22
from open_webui.utils.misc import (
33
add_or_update_system_message,
44
)
@@ -8,16 +8,28 @@
88

99
# inplace function: form_data is modified
1010
def apply_model_system_prompt_to_body(
11-
params: dict, form_data: dict, metadata: Optional[dict] = None
11+
params: dict, form_data: dict, metadata: Optional[dict] = None, user=None
1212
) -> dict:
1313
system = params.get("system", None)
1414
if not system:
1515
return form_data
1616

17+
# Legacy (API Usage)
18+
if user:
19+
template_params = {
20+
"user_name": user.name,
21+
"user_location": user.info.get("location") if user.info else None,
22+
}
23+
else:
24+
template_params = {}
25+
26+
system = prompt_template(system, **template_params)
27+
28+
# Metadata (WebUI Usage)
1729
if metadata:
18-
print("apply_model_system_prompt_to_body: metadata", metadata)
1930
variables = metadata.get("variables", {})
20-
system = prompt_variables_template(system, variables)
31+
if variables:
32+
system = prompt_variables_template(system, variables)
2133

2234
form_data["messages"] = add_or_update_system_message(
2335
system, form_data.get("messages", [])

package-lock.json

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "open-webui",
3-
"version": "0.5.9",
3+
"version": "0.5.10",
44
"private": true,
55
"scripts": {
66
"dev": "npm run pyodide:fetch && vite dev --host",

0 commit comments

Comments
 (0)