Skip to content

feat: context-aware greeting prompt embeds schema for relevant tables#260

Open
cpsievert wants to merge 7 commits into
mainfrom
worktree-context-aware-greeting
Open

feat: context-aware greeting prompt embeds schema for relevant tables#260
cpsievert wants to merge 7 commits into
mainfrom
worktree-context-aware-greeting

Conversation

@cpsievert

@cpsievert cpsievert commented Jun 23, 2026

Copy link
Copy Markdown
Contributor

Background

When querychat gained multi-table support (#195), schema context moved out of the system prompt and into a lazy tool (tool_get_schema): the LLM acquires data context on demand by calling the tool during a conversation. This works well for user queries — but it introduced a regression in greeting generation.

The greeting is produced in a tool-free client (no update_dashboard, no query tool), so the LLM has no way to call tool_get_schema to learn about the data. Before multi-table, the schema was always in the system prompt, so the greeting was naturally context-aware. After multi-table, it isn't — the LLM is flying blind when writing the opening message.

What this PR does

Restores greeting context-awareness by building a schema-aware prompt at greeting time, rather than relying on the system prompt or tool calls.

New greeting_tables parameter on QueryChat (R + Python, all frameworks — Shiny, Streamlit, Gradio) controls which tables' schema to embed:

  • None (default): auto — single-table apps embed the full schema (restoring pre-regression behavior); multi-table apps omit schema and instead prompt the LLM to encourage the user to explore what's available
  • True: embed all tables
  • False: no schema (explorer hint only)
  • list of names: embed only the named tables

New build_greeting_prompt() function (R + Python) encapsulates the construction logic — resolves which tables to include, fetches their schema, and prepends a GREETING_MARKER sentinel. The sentinel replaces a previous exact-string equality check for filtering the greeting turn out of conversation history; that check would have broken as soon as the prompt content changed.

generate_greeting() and mod_server updated in both packages to use build_greeting_prompt().

Test coverage

New tests cover build_greeting_prompt directly (single-table, multi-table, explicit list, True/False), generate_greeting() end-to-end with a mock client, and resolve_greeting_tables logic — in both R and Python.

cpsievert and others added 7 commits June 23, 2026 16:30
…tation

- Rename _GREETING_BASE_TEXT/_GREETING_EXPLORE_ADDENDUM to drop
  leading underscores (private module convention)
- Widen data_sources param from dict to Mapping in build_greeting_prompt
  and resolve_greeting_tables, fixing Pyright invariance errors
- Clarify GREETING_PROMPT backward-compat comment
- Rename misleading test to match what it actually verifies
Em-dash and arrow introduced in GREETING_EXPLORE_ADDENDUM and a comment
trigger R CMD check WARNING about non-portable characters.
@cpsievert cpsievert requested a review from gadenbuie June 23, 2026 22:01
@gadenbuie

Copy link
Copy Markdown
Contributor

I really like the overall idea and think the insight to fix this in the greeting generation is smart.

There are a couple things about this design that give me pause:

  • greeting_tables feels misplaced as an argument. Since it primarily exists for use with multiple tables, I think it'd be better to attach this argument to the .add_table() and .add_tables() methods where it's most relevant as an include_in_greeting argument.
  • Another angle for improving the extensibility of the greeting would be to let users customize the greeting prompt. This would let devs keep the dynamic greeting generation and mechanics but skip the potentially expensive schema prompts.
  • Related to the above, it'd be nice to keep the templating from the main system prompt, but if we're re-using the system prompt entirely we're including a bunch of extra information in the greeting prompt that we don't need to include. But we're also modifying the system prompt to remove tool details, so we there isn't a cache advantage here either. I think we trim down the greeting generation system prompt.
  • I also think we should have the greeting generation happen in a separate conversation rather than the main conversation. This changed in Adopt shinychat 0.4.0 greeting API with bookmark persistence #249 to be the default behavior, except in Python's dash/gradio/streamlit code paths which didn't have a shinychat greeting to migrate to. I certainly think there's room for talking through the trade-offs and benefits of how we handle the greeting in the main chat history, but I also think it's worth sticking with the "greeting in fresh session" approach initially and separately dealing with the "greeting in chat history" question directly and independently.

In talking through these ideas with Claude and reviewing the PR, I landed on an alternative API design that I think is worth considering in parallel. I'm working on a PR and will have something up shortly

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants