add a setting that tells the model the current date - #8879
Conversation
Models answered from their training cutoff, so Deep Research planned searches around 2023/2024 and web search looked for stale sources. Closes unslothai#8859. New global setting `include_current_date_in_prompt` in utils/current_date_prompt_settings.py, default on, exposed at GET/PUT /api/settings/current-date-prompt and as a toggle in Settings > Chat > Chat defaults. Where the date now lands: - local chat, with or without tools, applied once in openai_chat_completions - Deep Research, prefixed in _system_prompt_with_instructions so the planner, agent, audit and report calls all get it; stamped into the run config at creation so a run spanning midnight keeps its starting date - /v1/messages on every branch but the client-tool passthrough - self-hosted providers (vllm, ollama, llama_cpp, custom) via provider_is_self_hosted Left alone: hosted APIs and Codex, which state the date in their own context, and the llama-server passthrough, which forwards a caller's request verbatim. _build_tool_action_nudge no longer carries the date, so it rides the system prompt instead and a tool-less chat is no longer date-blind. Injection is idempotent on CURRENT_DATE_PROMPT_PREFIX: a research hop posts an already-dated prompt back through the chat route, and a second line would contradict the first after midnight. chat_count_tokens and anthropic_count_tokens apply the same rule as their generation twins, so counts still match what is sent.
for more information, see https://pre-commit.ci
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: ef5943d3ac
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| """Return the shared date sentence, or an empty string when the preference is off.""" | ||
| if not get_current_date_prompt_enabled(): | ||
| return "" | ||
| return f"{CURRENT_DATE_PROMPT_PREFIX}{(today or date.today()).isoformat()}." |
There was a problem hiding this comment.
Derive today's date from the caller's timezone
In remote, Colab, or shared-server deployments where the backend and user are in different timezones, date.today() supplies the server's calendar date. Around midnight this default-on feature therefore tells the model yesterday's or tomorrow's date, and Deep Research persists that incorrect value for the entire run. The request needs to provide the browser's timezone/date, or the application needs an explicit user timezone setting, rather than relying on the host timezone.
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
Not taking this one. date.today() is the same server-local call the tool nudge already used before this PR, so the date value's semantics are unchanged; what changed is only how often it is sent. There is no user or browser timezone anywhere in the request today, so honouring one means a new request field plus frontend plumbing and a per-user setting, which is a separate change rather than a fix to this behaviour. Studio also runs on localhost in the common case, where server and user share a timezone. Worth doing as a follow-up for remote and Colab deployments.
… date anthropic_count_tokens skipped the date whenever the caller sent any tools, but /messages only forwards verbatim on the client-tool passthrough. A Studio server-tool alias, or a template without tool-passthrough support, falls through to plain generation there and does carry the date, so the count under-reported those prompts. It now reproduces the same client_tools predicate the generation route uses. _prepend_current_date_to_messages returned on the first system turn, so a date on a later system or developer turn was missed and a second one got inserted. The scan now covers every system turn before anything is written.
|
@codex review |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 6f5e876210
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| const saveCurrentDatePrompt = async (enabled: boolean) => { | ||
| setIsSavingCurrentDatePrompt(true); | ||
| setCurrentDatePromptError(null); | ||
| try { | ||
| setCurrentDatePrompt(await updateCurrentDatePrompt(enabled)); |
There was a problem hiding this comment.
Recount context usage after changing the date prompt
After this save succeeds, the server changes the prompt that /chat/count_tokens and the next local generation will render, but the currently mounted chat retains its existing contextUsage snapshot. Because Settings is an overlay, closing it does not remount the chat or trigger ThreadContextUsageRecount, which only counts into a blank bar; enabling the date can therefore leave the context meter undercounting until a generation completes and may let a near-limit request exceed the available context. Clear and refresh the active thread's usage after the update succeeds.
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
Not taking this one. The date is a single short sentence, so the drift is roughly ten tokens, and the meter re-counts on the next message anyway. Reaching from the settings overlay into the active thread's usage store to force a recount is a change in another feature for that margin, and the near-limit case it describes is already handled by the server-side context check rather than the bar. Happy to revisit if the meter turns out to drift by an amount that actually changes a decision.
The inference router is also mounted at /v1, so a third party's sk-unsloth key reached the same handlers and a tool-less request came back with a system turn it never sent, which breaks a deterministic eval. _wants_current_date gates on _request_used_api_key, which already treats internal workflow keys as Studio, so Deep Research and the UI keep the date. The planner rule said never to put an older year in a query. Early in a year the most recent annual figures are the previous year's, so it now says to anchor on the stated date rather than a year the training data makes feel current. Pinned the current-date line off in the shared count-tokens backend helper so message-shape assertions do not depend on the host's stored setting, and added test_chat_count_tokens_prices_the_current_date for the date's own effect on the count.
|
@codex review |
|
@codex review |
1 similar comment
|
@codex review |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: c6888ec286
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
…t parts _wants_current_date gated on _request_used_api_key, which excludes Studio's own workflow keys, so the date reached two callers that compose their own prompts. routes/data_recipe/jobs.py mints an internal key and points user-authored recipes at /v1, where the injected instruction would change generated datasets. Deep Research decides once at run creation and stamps the answer into its config, so a run created while the preference was off picked up a fresh date as soon as the preference was turned back on. Gating on _request_has_api_key leaves both to their own prompt and limits the date to an interactive session. _states_a_date now reads content parts as well as plain strings, so a date already present in a text-part array suppresses a second one.
|
@codex review |
1 similar comment
|
@codex review |
|
Codex Review: Didn't find any major issues. Another round soon, please! Reviewed commit: ℹ️ About Codex in GitHubCodex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
If Codex has suggestions, it will comment; otherwise it will react with 👍. When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback". |
Closes #8859.
Models answered from their training cutoff, so Deep Research planned its searches around 2023/2024 and web search went looking for stale sources. There was no way to fix it short of editing the system prompt every day.
What this adds
A global setting,
include_current_date_in_prompt, default on, instudio/backend/utils/current_date_prompt_settings.py. It is served atGET/PUT /api/settings/current-date-promptand shown as a toggle in Settings > Chat > Chat defaults.Where the date now lands:
openai_chat_completions_system_prompt_with_instructionsso the planner, agent, audit and report calls all get it. The date is stamped into the run config at creation, so a run spanning midnight keeps the date it started on/v1/messageson every branch but the client-tool passthroughprovider_is_self_hostedDeliberately left alone: hosted APIs and Codex, which state the date in their own context, and the llama-server passthrough, which forwards a caller's own request verbatim.
_build_tool_action_nudgeno longer carries the date. It rides the system prompt instead, so a tool-less chat is no longer date-blind. Injection is idempotent onCURRENT_DATE_PROMPT_PREFIX: a research hop posts an already-dated prompt back through the chat route, and a second line would contradict the first once the run crosses midnight.chat_count_tokensandanthropic_count_tokensfollow the same rule as their generation twins, so counts still match what is sent.Verification
Manually tested end to end against a running Studio instance.
Local MLX model (Qwen3-0.6B-4bit), asked for today's date:
2024-05-05(its training-cutoff guess, the reported bug)2026-08-15With a user system prompt set, both survive:
Today's date is **2026-08-15**. BANANA.Against an OpenAI-compatible server that echoes the system prompt it received:
A prompt that already states a date is left untouched, including when Deep Research buries it under its instructions header, so no hop is dated twice.
Token counts track generation: 42 -> 89 with the setting on for a normal chat, and 42 either way on the verbatim passthrough.
The settings toggle was driven in a browser: it reads server state, writes on click, and a fresh session reads back the persisted value.
Ruff format and check clean, i18n strict parity clean across all 12 locales,
tscclean, 763 focused backend tests pass. No GPU checks were run; none apply to this change.