Skip to content

Commit f58df05

Browse files
cpsievertCopilot
andauthored
chore: align and tidy greeting logic (#133)
* chore: align and tidy greeting logic * Update pkg-py/docs/greet.qmd Co-authored-by: Copilot <[email protected]> * fix: formatting * `air format` (GitHub Actions) --------- Co-authored-by: Copilot <[email protected]> Co-authored-by: cpsievert <[email protected]>
1 parent 7e47ebf commit f58df05

File tree

5 files changed

+51
-31
lines changed

5 files changed

+51
-31
lines changed

pkg-py/docs/greet.qmd

Lines changed: 27 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,17 @@ title: Greet users
55

66
### Provide a greeting
77

8-
When the querychat UI first appears, you will usually want it to greet the user with some basic instructions. By default, these instructions are auto-generated every time a user arrives; this is slow, wasteful, and unpredictable. Instead, you should create a greeting file and pass it when creating your `QueryChat` object:
8+
When the querychat UI first appears, you will usually want it to greet the user with some basic instructions. By default, these instructions are auto-generated every time a user arrives. In a production setting with multiple users/visitors, this is slow, wasteful, and non-deterministic. Instead, you should create a greeting file and pass it when creating your `QueryChat` object:
99

10-
```python
10+
```{.python filename="titanic-app.py"}
11+
from querychat import QueryChat
12+
from querychat.data import titanic
1113
from pathlib import Path
12-
qc = QueryChat(titanic, "titanic", greeting=Path("greeting.md"))
14+
15+
app_dir = Path(__file__).parent
16+
17+
qc = QueryChat(titanic(), "titanic", greeting=app_dir / "greeting.md")
18+
app = qc.app()
1319
```
1420

1521
You can provide suggestions to the user by using the `<span class="suggestion"> </span>` tag:
@@ -33,13 +39,13 @@ You can see this behavior in our [`querychat template`](https://shiny.posit.co/p
3339

3440
If you need help coming up with a greeting, you can use the `.generate_greeting()` method:
3541

36-
```python
42+
```{.python filename="penguins-greeting.py"}
3743
from palmerpenguins import load_penguins
3844
from querychat import QueryChat
45+
from pathlib import Path
3946
4047
# Create QueryChat object with your dataset
41-
penguins = load_penguins()
42-
qc = QueryChat(penguins, "penguins")
48+
qc = QueryChat(load_penguins(), "penguins")
4349
4450
# Generate a greeting (this calls the LLM)
4551
greeting_text = qc.generate_greeting()
@@ -50,9 +56,21 @@ greeting_text = qc.generate_greeting()
5056
# Save it for reuse
5157
with open("penguins_greeting.md", "w") as f:
5258
f.write(greeting_text)
59+
```
60+
61+
This approach generates a greeting once and saves it for reuse, avoiding the latency and cost of generating it for every user.
62+
63+
```{.python filename="penguins-app.py"}
64+
from palmerpenguins import load_penguins
65+
from querychat import QueryChat
66+
from pathlib import Path
5367
5468
# Then use the saved greeting in your app
55-
qc = QueryChat(penguins, "penguins", greeting=Path("penguins_greeting.md"))
69+
app_dir = Path(__file__).parent
70+
qc = QueryChat(
71+
load_penguins(),
72+
"penguins",
73+
greeting=app_dir / "penguins_greeting.md",
74+
)
75+
app = qc.app()
5676
```
57-
58-
This approach generates a greeting once and saves it for reuse, avoiding the latency and cost of generating it for every user.

pkg-py/src/querychat/_querychat.py

Lines changed: 2 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33
import copy
44
import os
55
import re
6-
import sys
76
from pathlib import Path
87
from typing import TYPE_CHECKING, Literal, Optional, overload
98

@@ -17,7 +16,7 @@
1716

1817
from ._datasource import DataFrameSource, DataSource, SQLAlchemySource
1918
from ._icons import bs_icon
20-
from ._querychat_module import ServerValues, mod_server, mod_ui
19+
from ._querychat_module import GREETING_PROMPT, ServerValues, mod_server, mod_ui
2120

2221
if TYPE_CHECKING:
2322
import pandas as pd
@@ -48,14 +47,6 @@ def __init__(
4847

4948
self.id = id or table_name
5049

51-
if greeting is None:
52-
print(
53-
"Warning: No greeting provided; the LLM will be invoked at conversation start to generate one. "
54-
"For faster startup, lower cost, and determinism, please save a greeting and pass it to init().",
55-
"You can also use `querychat.greeting()` to help generate a greeting.",
56-
file=sys.stderr,
57-
)
58-
5950
self.greeting = greeting.read_text() if isinstance(greeting, Path) else greeting
6051

6152
prompt = get_system_prompt(
@@ -244,8 +235,7 @@ def generate_greeting(self, *, echo: Literal["none", "output"] = "none"):
244235
"""
245236
client = copy.deepcopy(self._client)
246237
client.set_turns([])
247-
prompt = "Please give me a friendly greeting. Include a few sample prompts in a two-level bulleted list."
248-
return str(client.chat(prompt, echo=echo))
238+
return str(client.chat(GREETING_PROMPT, echo=echo))
249239

250240
@property
251241
def system_prompt(self) -> str:

pkg-py/src/querychat/_querychat_module.py

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
from __future__ import annotations
22

33
import copy
4+
import warnings
45
from dataclasses import dataclass
56
from pathlib import Path
67
from typing import TYPE_CHECKING, Callable, Union
@@ -134,10 +135,14 @@ async def greet_on_startup():
134135
if greeting:
135136
await chat_ui.append_message(greeting)
136137
elif greeting is None:
137-
stream = await chat.stream_async(
138-
"Please give me a friendly greeting. Include a few sample prompts in a two-level bulleted list.",
139-
echo="none",
138+
warnings.warn(
139+
"No greeting provided to `QueryChat()`. Using the LLM `client` to generate one now. "
140+
"For faster startup, lower cost, and determinism, consider providing a greeting "
141+
"to `QueryChat()` and `.generate_greeting()` to generate one beforehand.",
142+
GreetWarning,
143+
stacklevel=2,
140144
)
145+
stream = await chat.stream_async(GREETING_PROMPT, echo="none")
141146
await chat_ui.append_message_stream(stream)
142147

143148
has_greeted.set(True)
@@ -180,3 +185,10 @@ def _on_restore(x: RestoreState) -> None:
180185
has_greeted.set(vals["querychat_has_greeted"])
181186

182187
return ServerValues(df=filtered_df, sql=sql, title=title, client=chat)
188+
189+
190+
GREETING_PROMPT: str = "Please give me a friendly greeting. Include a few sample prompts in a two-level bulleted list."
191+
192+
193+
class GreetWarning(Warning):
194+
"""Warning raised when no greeting is provided to QueryChat."""

pkg-r/R/QueryChat.R

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -511,8 +511,7 @@ QueryChat <- R6::R6Class(
511511
chat <- private$.client$clone()
512512
chat$set_turns(list())
513513

514-
prompt <- "Please give me a friendly greeting. Include a few sample prompts in a two-level bulleted list."
515-
as.character(chat$chat(prompt, echo = echo))
514+
as.character(chat$chat(GREETING_PROMPT, echo = echo))
516515
},
517516

518517
#' @description

pkg-r/R/querychat_module.R

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -71,13 +71,11 @@ mod_server <- function(
7171
greeting_content <- if (!is.null(greeting) && any(nzchar(greeting))) {
7272
greeting
7373
} else {
74-
# Generate greeting on the fly if none provided
7574
rlang::warn(c(
76-
"No greeting provided; generating one now. This adds latency and cost.",
77-
"i" = "Consider using $generate_greeting() to create a reusable greeting."
75+
"No greeting provided to `QueryChat()`. Using the LLM `client` to generate one now.",
76+
"i" = "For faster startup, lower cost, and determinism, consider providing a greeting to `QueryChat()` and `$generate_greeting()` to generate one beforehand."
7877
))
79-
prompt <- "Please give me a friendly greeting. Include a few sample prompts in a two-level bulleted list."
80-
chat$stream_async(prompt)
78+
chat$stream_async(GREETING_PROMPT)
8179
}
8280

8381
shinychat::chat_append("chat", greeting_content)
@@ -137,3 +135,6 @@ mod_server <- function(
137135
)
138136
})
139137
}
138+
139+
140+
GREETING_PROMPT <- "Please give me a friendly greeting. Include a few sample prompts in a two-level bulleted list."

0 commit comments

Comments
 (0)