Skip to content

Commit dc3b2f1

Browse files
authored
Merge pull request open-webui#9190 from open-webui/dev
0.5.8
2 parents b72150c + 1ab66e8 commit dc3b2f1

File tree

147 files changed

+4236
-1743
lines changed

Some content is hidden

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

147 files changed

+4236
-1743
lines changed

CHANGELOG.md

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,35 @@ 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.8] - 2025-02-05
9+
10+
### Added
11+
12+
- **🖥️ Code Interpreter**: Models can now execute code in real time to refine their answers dynamically, running securely within a sandboxed browser environment using Pyodide. Perfect for calculations, data analysis, and AI-assisted coding tasks!
13+
- **💬 Redesigned Chat Input UI**: Enjoy a sleeker and more intuitive message input with improved feature selection, making it easier than ever to toggle tools, enable search, and interact with AI seamlessly.
14+
- **🛠️ Native Tool Calling Support (Experimental)**: Supported models can now call tools natively, reducing query latency and improving contextual responses. More enhancements coming soon!
15+
- **🔗 Exa Search Engine Integration**: A new search provider has been added, allowing users to retrieve up-to-date and relevant information without leaving the chat interface.
16+
- **🌍 Localized Dates & Times**: Date and time formats now match your system locale, ensuring a more natural, region-specific experience.
17+
- **📎 User Headers for External Embedding APIs**: API calls to external embedding services now include user-related headers.
18+
- **🌍 "Always On" Web Search Toggle**: A new option under Settings > Interface allows users to enable Web Search by default—transform Open WebUI into your go-to search engine, ensuring AI-powered results with every query.
19+
- **🚀 General Performance & Stability**: Significant improvements across the platform for a faster, more reliable experience.
20+
- **🖼️ UI/UX Enhancements**: Numerous design refinements improving readability, responsiveness, and accessibility.
21+
- **🌍 Improved Translations**: Chinese, Korean, French, Ukrainian and Serbian translations have been updated with refined terminologies for better clarity.
22+
23+
### Fixed
24+
25+
- **🔄 OAuth Name Field Fallback**: Resolves OAuth login failures by using the email field as a fallback when a name is missing.
26+
- **🔑 Google Drive Credentials Restriction**: Ensures only authenticated users can access Google Drive credentials for enhanced security.
27+
- **🌐 DuckDuckGo Search Rate Limit Handling**: Fixes issues where users would encounter 202 errors due to rate limits when using DuckDuckGo for web search.
28+
- **📁 File Upload Permission Indicator**: Users are now notified when they lack permission to upload files, improving clarity on system restrictions.
29+
- **🔧 Max Tokens Issue**: Fixes cases where 'max_tokens' were not applied correctly, ensuring proper model behavior.
30+
- **🔍 Validation for RAG Web Search URLs**: Filters out invalid or unsupported URLs when using web-based retrieval augmentation.
31+
- **🖋️ Title Generation Bug**: Fixes inconsistencies in title generation, ensuring proper chat organization.
32+
33+
### Removed
34+
35+
- **⚡ Deprecated Non-Web Worker Pyodide Execution**: Moves entirely to browser sandboxing for better performance and security.
36+
837
## [0.5.7] - 2025-01-23
938

1039
### Added

backend/open_webui/config.py

Lines changed: 70 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -927,6 +927,12 @@ def oidc_oauth_register(client):
927927
== "true"
928928
)
929929

930+
USER_PERMISSIONS_FEATURES_CODE_INTERPRETER = (
931+
os.environ.get("USER_PERMISSIONS_FEATURES_CODE_INTERPRETER", "True").lower()
932+
== "true"
933+
)
934+
935+
930936
DEFAULT_USER_PERMISSIONS = {
931937
"workspace": {
932938
"models": USER_PERMISSIONS_WORKSPACE_MODELS_ACCESS,
@@ -944,6 +950,7 @@ def oidc_oauth_register(client):
944950
"features": {
945951
"web_search": USER_PERMISSIONS_FEATURES_WEB_SEARCH,
946952
"image_generation": USER_PERMISSIONS_FEATURES_IMAGE_GENERATION,
953+
"code_interpreter": USER_PERMISSIONS_FEATURES_CODE_INTERPRETER,
947954
},
948955
}
949956

@@ -1094,21 +1101,27 @@ class BannerModel(BaseModel):
10941101
os.environ.get("TITLE_GENERATION_PROMPT_TEMPLATE", ""),
10951102
)
10961103

1097-
DEFAULT_TITLE_GENERATION_PROMPT_TEMPLATE = """Create a concise, 3-5 word title with an emoji as a title for the chat history, in the given language. Suitable Emojis for the summary can be used to enhance understanding but avoid quotation marks or special formatting. RESPOND ONLY WITH THE TITLE TEXT.
1098-
1099-
Examples of titles:
1100-
📉 Stock Market Trends
1101-
🍪 Perfect Chocolate Chip Recipe
1102-
Evolution of Music Streaming
1103-
Remote Work Productivity Tips
1104-
Artificial Intelligence in Healthcare
1105-
🎮 Video Game Development Insights
1106-
1104+
DEFAULT_TITLE_GENERATION_PROMPT_TEMPLATE = """### Task:
1105+
Generate a concise, 3-5 word title with an emoji summarizing the chat history.
1106+
### Guidelines:
1107+
- The title should clearly represent the main theme or subject of the conversation.
1108+
- Use emojis that enhance understanding of the topic, but avoid quotation marks or special formatting.
1109+
- Write the title in the chat's primary language; default to English if multilingual.
1110+
- Prioritize accuracy over excessive creativity; keep it clear and simple.
1111+
### Output:
1112+
JSON format: { "title": "your concise title here" }
1113+
### Examples:
1114+
- { "title": "📉 Stock Market Trends" },
1115+
- { "title": "🍪 Perfect Chocolate Chip Recipe" },
1116+
- { "title": "Evolution of Music Streaming" },
1117+
- { "title": "Remote Work Productivity Tips" },
1118+
- { "title": "Artificial Intelligence in Healthcare" },
1119+
- { "title": "🎮 Video Game Development Insights" }
1120+
### Chat History:
11071121
<chat_history>
11081122
{{MESSAGES:END:2}}
11091123
</chat_history>"""
11101124

1111-
11121125
TAGS_GENERATION_PROMPT_TEMPLATE = PersistentConfig(
11131126
"TAGS_GENERATION_PROMPT_TEMPLATE",
11141127
"task.tags.prompt_template",
@@ -1277,7 +1290,28 @@ class BannerModel(BaseModel):
12771290
)
12781291

12791292

1280-
DEFAULT_TOOLS_FUNCTION_CALLING_PROMPT_TEMPLATE = """Available Tools: {{TOOLS}}\nReturn an empty string if no tools match the query. If a function tool matches, construct and return a JSON object in the format {\"name\": \"functionName\", \"parameters\": {\"requiredFunctionParamKey\": \"requiredFunctionParamValue\"}} using the appropriate tool and its parameters. Only return the object and limit the response to the JSON object without additional text."""
1293+
DEFAULT_TOOLS_FUNCTION_CALLING_PROMPT_TEMPLATE = """Available Tools: {{TOOLS}}
1294+
1295+
Your task is to choose and return the correct tool(s) from the list of available tools based on the query. Follow these guidelines:
1296+
1297+
- Return only the JSON object, without any additional text or explanation.
1298+
1299+
- If no tools match the query, return an empty array:
1300+
{
1301+
"tool_calls": []
1302+
}
1303+
1304+
- If one or more tools match the query, construct a JSON response containing a "tool_calls" array with objects that include:
1305+
- "name": The tool's name.
1306+
- "parameters": A dictionary of required parameters and their corresponding values.
1307+
1308+
The format for the JSON response is strictly:
1309+
{
1310+
"tool_calls": [
1311+
{"name": "toolName1", "parameters": {"key1": "value1"}},
1312+
{"name": "toolName2", "parameters": {"key2": "value2"}}
1313+
]
1314+
}"""
12811315

12821316

12831317
DEFAULT_EMOJI_GENERATION_PROMPT_TEMPLATE = """Your task is to reflect the speaker's likely facial expression through a fitting emoji. Interpret emotions from the message and reflect their facial expression using fitting, diverse emojis (e.g., 😊, 😢, 😡, 😱).
@@ -1290,6 +1324,24 @@ class BannerModel(BaseModel):
12901324
12911325
Responses from models: {{responses}}"""
12921326

1327+
1328+
DEFAULT_CODE_INTERPRETER_PROMPT = """
1329+
#### Tools Available
1330+
1331+
1. **Code Interpreter**: `<code_interpreter type="code" lang="python"></code_interpreter>`
1332+
- You have access to a Python shell that runs directly in the user's browser, enabling fast execution of code for analysis, calculations, or problem-solving. Use it in this response.
1333+
- The Python code you write can incorporate a wide array of libraries, handle data manipulation or visualization, perform API calls for web-related tasks, or tackle virtually any computational challenge. Use this flexibility to **think outside the box, craft elegant solutions, and harness Python's full potential**.
1334+
- To use it, **you must enclose your code within `<code_interpreter type="code" lang="python">` XML tags** and stop right away. If you don't, the code won't execute. Do NOT use triple backticks.
1335+
- When coding, **always aim to print meaningful outputs** (e.g., results, tables, summaries, or visuals) to better interpret and verify the findings. Avoid relying on implicit outputs; prioritize explicit and clear print statements so the results are effectively communicated to the user.
1336+
- After obtaining the printed output, **always provide a concise analysis, interpretation, or next steps to help the user understand the findings or refine the outcome further.**
1337+
- 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.
1338+
- 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.
1339+
- 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.**
1341+
1342+
Ensure that the tools are effectively utilized to achieve the highest-quality analysis for the user."""
1343+
1344+
12931345
####################################
12941346
# Vector Database
12951347
####################################
@@ -1319,6 +1371,7 @@ class BannerModel(BaseModel):
13191371

13201372
MILVUS_URI = os.environ.get("MILVUS_URI", f"{DATA_DIR}/vector_db/milvus.db")
13211373
MILVUS_DB = os.environ.get("MILVUS_DB", "default")
1374+
MILVUS_TOKEN = os.environ.get("MILVUS_TOKEN", None)
13221375

13231376
# Qdrant
13241377
QDRANT_URI = os.environ.get("QDRANT_URI", None)
@@ -1699,6 +1752,11 @@ class BannerModel(BaseModel):
16991752
os.environ.get("BING_SEARCH_V7_SUBSCRIPTION_KEY", ""),
17001753
)
17011754

1755+
EXA_API_KEY = PersistentConfig(
1756+
"EXA_API_KEY",
1757+
"rag.web.search.exa_api_key",
1758+
os.getenv("EXA_API_KEY", ""),
1759+
)
17021760

17031761
RAG_WEB_SEARCH_RESULT_COUNT = PersistentConfig(
17041762
"RAG_WEB_SEARCH_RESULT_COUNT",

backend/open_webui/constants.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ def __str__(self) -> str:
5757
)
5858

5959
FILE_NOT_SENT = "FILE_NOT_SENT"
60-
FILE_NOT_SUPPORTED = "Oops! It seems like the file format you're trying to upload is not supported. Please upload a file with a supported format (e.g., JPG, PNG, PDF, TXT) and try again."
60+
FILE_NOT_SUPPORTED = "Oops! It seems like the file format you're trying to upload is not supported. Please upload a file with a supported format and try again."
6161

6262
NOT_FOUND = "We could not find what you're looking for :/"
6363
USER_NOT_FOUND = "We could not find what you're looking for :/"

backend/open_webui/env.py

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -356,14 +356,22 @@ def parse_section(section):
356356
), # DEPRECATED: remove at next major version
357357
)
358358

359-
WEBUI_SESSION_COOKIE_SAME_SITE = os.environ.get(
360-
"WEBUI_SESSION_COOKIE_SAME_SITE",
361-
os.environ.get("WEBUI_SESSION_COOKIE_SAME_SITE", "lax"),
359+
WEBUI_SESSION_COOKIE_SAME_SITE = os.environ.get("WEBUI_SESSION_COOKIE_SAME_SITE", "lax")
360+
361+
WEBUI_SESSION_COOKIE_SECURE = (
362+
os.environ.get("WEBUI_SESSION_COOKIE_SECURE", "false").lower() == "true"
363+
)
364+
365+
WEBUI_AUTH_COOKIE_SAME_SITE = os.environ.get(
366+
"WEBUI_AUTH_COOKIE_SAME_SITE", WEBUI_SESSION_COOKIE_SAME_SITE
362367
)
363368

364-
WEBUI_SESSION_COOKIE_SECURE = os.environ.get(
365-
"WEBUI_SESSION_COOKIE_SECURE",
366-
os.environ.get("WEBUI_SESSION_COOKIE_SECURE", "false").lower() == "true",
369+
WEBUI_AUTH_COOKIE_SECURE = (
370+
os.environ.get(
371+
"WEBUI_AUTH_COOKIE_SECURE",
372+
os.environ.get("WEBUI_SESSION_COOKIE_SECURE", "false"),
373+
).lower()
374+
== "true"
367375
)
368376

369377
if WEBUI_AUTH and WEBUI_SECRET_KEY == "":

backend/open_webui/main.py

Lines changed: 23 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -177,6 +177,7 @@
177177
BING_SEARCH_V7_ENDPOINT,
178178
BING_SEARCH_V7_SUBSCRIPTION_KEY,
179179
BRAVE_SEARCH_API_KEY,
180+
EXA_API_KEY,
180181
KAGI_SEARCH_API_KEY,
181182
MOJEEK_SEARCH_API_KEY,
182183
GOOGLE_PSE_API_KEY,
@@ -523,6 +524,7 @@ async def lifespan(app: FastAPI):
523524
app.state.config.JINA_API_KEY = JINA_API_KEY
524525
app.state.config.BING_SEARCH_V7_ENDPOINT = BING_SEARCH_V7_ENDPOINT
525526
app.state.config.BING_SEARCH_V7_SUBSCRIPTION_KEY = BING_SEARCH_V7_SUBSCRIPTION_KEY
527+
app.state.config.EXA_API_KEY = EXA_API_KEY
526528

527529
app.state.config.RAG_WEB_SEARCH_RESULT_COUNT = RAG_WEB_SEARCH_RESULT_COUNT
528530
app.state.config.RAG_WEB_SEARCH_CONCURRENT_REQUESTS = RAG_WEB_SEARCH_CONCURRENT_REQUESTS
@@ -859,6 +861,7 @@ async def chat_completion(
859861
if model_id not in request.app.state.MODELS:
860862
raise Exception("Model not found")
861863
model = request.app.state.MODELS[model_id]
864+
model_info = Models.get_model_by_id(model_id)
862865

863866
# Check if user has access to the model
864867
if not BYPASS_MODEL_ACCESS_CONTROL and user.role == "user":
@@ -875,12 +878,25 @@ async def chat_completion(
875878
"tool_ids": form_data.get("tool_ids", None),
876879
"files": form_data.get("files", None),
877880
"features": form_data.get("features", None),
881+
"variables": form_data.get("variables", None),
882+
"model": model_info,
883+
**(
884+
{"function_calling": "native"}
885+
if form_data.get("params", {}).get("function_calling") == "native"
886+
or (
887+
model_info
888+
and model_info.params.model_dump().get("function_calling")
889+
== "native"
890+
)
891+
else {}
892+
),
878893
}
879894
form_data["metadata"] = metadata
880895

881-
form_data, events = await process_chat_payload(
896+
form_data, metadata, events = await process_chat_payload(
882897
request, form_data, metadata, user, model
883898
)
899+
884900
except Exception as e:
885901
raise HTTPException(
886902
status_code=status.HTTP_400_BAD_REQUEST,
@@ -889,6 +905,7 @@ async def chat_completion(
889905

890906
try:
891907
response = await chat_completion_handler(request, form_data, user)
908+
892909
return await process_chat_response(
893910
request, response, form_data, user, events, metadata, tasks
894911
)
@@ -1007,10 +1024,6 @@ async def get_app_config(request: Request):
10071024
else {}
10081025
),
10091026
},
1010-
"google_drive": {
1011-
"client_id": GOOGLE_DRIVE_CLIENT_ID.value,
1012-
"api_key": GOOGLE_DRIVE_API_KEY.value,
1013-
},
10141027
**(
10151028
{
10161029
"default_models": app.state.config.DEFAULT_MODELS,
@@ -1030,6 +1043,10 @@ async def get_app_config(request: Request):
10301043
"max_count": app.state.config.FILE_MAX_COUNT,
10311044
},
10321045
"permissions": {**app.state.config.USER_PERMISSIONS},
1046+
"google_drive": {
1047+
"client_id": GOOGLE_DRIVE_CLIENT_ID.value,
1048+
"api_key": GOOGLE_DRIVE_API_KEY.value,
1049+
},
10331050
}
10341051
if user is not None
10351052
else {}
@@ -1063,7 +1080,7 @@ async def get_app_version():
10631080

10641081

10651082
@app.get("/api/version/updates")
1066-
async def get_app_latest_release_version():
1083+
async def get_app_latest_release_version(user=Depends(get_verified_user)):
10671084
if OFFLINE_MODE:
10681085
log.debug(
10691086
f"Offline mode is enabled, returning current version as latest version"

0 commit comments

Comments
 (0)