feat: the starter-prompt pool is built once and regenerated from the admin button only, on gpt-4.1-mini by default; the question box sits two-thirds down before a chat and at the bottom during one
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Dv6sqaY6Vq3ChZHMem3cnU
This commit is contained in:
parent
4119788815
commit
4127e2d101
6 changed files with 27 additions and 8 deletions
|
|
@ -266,7 +266,7 @@ DB_PASSWORD=pedscribe_secret_change_me
|
|||
# CLINICAL_ASSISTANT_PROMPT_MODEL= # model that writes the starter prompts
|
||||
# CLINICAL_ASSISTANT_PROMPT_POOL_TARGET=1000
|
||||
# CLINICAL_ASSISTANT_PROMPT_POOL_KEY=clinical-assistant:prompt-pool:v2
|
||||
# CLINICAL_ASSISTANT_PROMPT_POOL_REFRESH_MS=
|
||||
# CLINICAL_ASSISTANT_PROMPT_POOL_REFRESH_MS= # 0 (default): no schedule, admin button only; a positive number of ms adds a timer
|
||||
# CLINICAL_ASSISTANT_PROMPT_POOL_WARMUP_DELAY_MS=
|
||||
# CLINICAL_ASSISTANT_EXAMPLE_CACHE_MS=600000
|
||||
# PATIENT_TAKEHOME_BEHAVIOR= # overrides the admin-editable take-home guidance
|
||||
|
|
|
|||
|
|
@ -117,7 +117,7 @@ falls back to the default in the right-hand column.
|
|||
| `clinical_assistant.system_behavior` | Admin-editable assistant behavior guidance |
|
||||
| `clinical_assistant.image_behavior` | Guidance for the `generate_image` tool |
|
||||
| `clinical_assistant.patient_takehome_behavior` | Guidance for patient take-home text |
|
||||
| `clinical_assistant.prompt_model` | Model that generates the starter prompt pool |
|
||||
| `clinical_assistant.prompt_model` | Model that generates the starter prompt pool (default `openrouter-gpt-4.1-mini`) |
|
||||
| `clinical_assistant.translate_provider` | Translation provider. `libretranslate` is the only value the server accepts |
|
||||
| `clinical_assistant.citations_enabled` | Legacy key, read only as a fallback for `show_sources` |
|
||||
|
||||
|
|
@ -168,9 +168,9 @@ a setting falls back to.
|
|||
| `CLINICAL_ASSISTANT_MCP_WARMUP_DELAY_MS` | 5000 | Delay before that warmup. |
|
||||
| `CLINICAL_ASSISTANT_CONVERSATION_CHARS` | 120000 | Input budget in UTF-16 code units, when the setting is empty. |
|
||||
| `CLINICAL_ASSISTANT_IMAGE_MODEL` | `openai-gpt-image-1` | Image model, when the setting is empty. |
|
||||
| `CLINICAL_ASSISTANT_PROMPT_MODEL` | — | Model for the starter prompt pool, when the setting is empty. |
|
||||
| `CLINICAL_ASSISTANT_PROMPT_MODEL` | `openrouter-gpt-4.1-mini` | Model for the starter prompt pool, when the setting is empty. A non-reasoning model. |
|
||||
| `CLINICAL_ASSISTANT_PROMPT_POOL_TARGET` | 1000 | How many example prompts to generate. |
|
||||
| `CLINICAL_ASSISTANT_PROMPT_POOL_REFRESH_MS` | 7 days | How often the pool regenerates. `0` disables refresh. |
|
||||
| `CLINICAL_ASSISTANT_PROMPT_POOL_REFRESH_MS` | `0` | No schedule: the pool is built once, kept in Redis (with a last-good copy and a database snapshot), and regenerated only from Admin → Clinical Assistant → Regenerate. A positive value adds a timer. |
|
||||
| `CLINICAL_ASSISTANT_PROMPT_POOL_KEY` | `clinical-assistant:prompt-pool:v2` | Redis key holding the pool. |
|
||||
| `CLINICAL_ASSISTANT_PROMPT_POOL_WARMUP_DELAY_MS` | 15000 | Delay before the pool warms at boot. |
|
||||
| `CLINICAL_ASSISTANT_EXAMPLE_CACHE_MS` | 600000 | How long the examples endpoint caches its answer. |
|
||||
|
|
|
|||
|
|
@ -60,7 +60,7 @@ keys):
|
|||
### Starter questions
|
||||
| Setting | Meaning |
|
||||
|---|---|
|
||||
| `clinical_assistant.prompt_model` | The model that writes the starter-question pool. Use a **non-reasoning** model (`openrouter-gpt-4.1-mini` in production): a reasoning model spends the whole completion budget thinking about a 20-question JSON list and returns nothing. Falls back to `clinical_assistant.chat_model`, then `models.default`. |
|
||||
| `clinical_assistant.prompt_model` | The model that writes the starter-question pool. Use a **non-reasoning** model (`openrouter-gpt-4.1-mini` in production): a reasoning model spends the whole completion budget thinking about a 20-question JSON list and returns nothing. Defaults to `openrouter-gpt-4.1-mini` when unset. The pool is generated once and then only when an admin presses Regenerate; it is stored in Redis with a database snapshot. |
|
||||
|
||||
### Embeddings
|
||||
|
||||
|
|
|
|||
|
|
@ -14,6 +14,17 @@
|
|||
.assistant-new-chat:hover { border-color:var(--blue); background:var(--blue-light); }
|
||||
.assistant-main { display:flex; flex-direction:column; min-height:0; min-width:0; }
|
||||
#assistant-chat-view { display:grid; grid-template-rows:minmax(0,1fr) auto; min-height:0; min-width:0; }
|
||||
/* Where the question box sits. With no conversation yet, the heading and the
|
||||
starter questions are centred in a shorter view and the box sits just under
|
||||
them, about two-thirds of the way down — neither hugging the header nor
|
||||
pinned to the floor. Once there are messages the view fills the screen and
|
||||
the box stays at the bottom, where a chat box belongs. */
|
||||
@media (min-width: 961px) {
|
||||
#assistant-chat-view:not(:has(.assistant-msg)) { min-height:min(62vh, 640px); }
|
||||
#assistant-chat-view:has(.assistant-msg) { min-height:calc(100vh - 190px); }
|
||||
.assistant-messages:not(:has(.assistant-msg)) { display:flex; flex-direction:column; justify-content:center; }
|
||||
.assistant-messages:not(:has(.assistant-msg)) .assistant-empty { margin:0 auto; }
|
||||
}
|
||||
.assistant-messages { padding:16px; max-height:none; overflow-y:auto; overflow-x:hidden; background:transparent; min-width:0; }
|
||||
.assistant-empty { max-width:680px; margin:50px auto; text-align:center; color:var(--g500); }
|
||||
.assistant-empty i { font-size:34px; color:var(--blue); margin-bottom:10px; }
|
||||
|
|
|
|||
|
|
@ -256,7 +256,11 @@ var PROMPT_VERSION = 2;
|
|||
function createClinicalPromptPool(opts) {
|
||||
opts = opts || {};
|
||||
var cacheMs = positiveInt(process.env.CLINICAL_ASSISTANT_EXAMPLE_CACHE_MS, 10 * 60 * 1000);
|
||||
var refreshMs = nonNegativeInt(process.env.CLINICAL_ASSISTANT_PROMPT_POOL_REFRESH_MS, 7 * 24 * 60 * 60 * 1000);
|
||||
// No schedule by default: the pool is built once (when there is none, or the
|
||||
// prompt version changed) and after that only when an admin presses
|
||||
// Regenerate. It lives in Redis with a last-good copy and a database
|
||||
// snapshot, so a restart never rebuilds it. A positive value restores a timer.
|
||||
var refreshMs = nonNegativeInt(process.env.CLINICAL_ASSISTANT_PROMPT_POOL_REFRESH_MS, 0);
|
||||
var ttlSeconds = refreshMs > 0 ? Math.max(3600, Math.ceil(refreshMs / 1000) * 2) : 0;
|
||||
var target = positiveInt(process.env.CLINICAL_ASSISTANT_PROMPT_POOL_TARGET, 1000);
|
||||
var redisBaseKey = String(process.env.CLINICAL_ASSISTANT_PROMPT_POOL_KEY || 'clinical-assistant:prompt-pool:v2').replace(/:all$/, '');
|
||||
|
|
@ -328,7 +332,9 @@ function createClinicalPromptPool(opts) {
|
|||
|
||||
async function buildCorpusPromptPool() {
|
||||
var taxonomy = taxonomyWithQuotas(target);
|
||||
var chatModel = await opts.getSetting('clinical_assistant.prompt_model', '') || process.env.CLINICAL_ASSISTANT_PROMPT_MODEL || await opts.getSetting('clinical_assistant.chat_model', '') || await opts.getSetting('models.default', '');
|
||||
// A small non-reasoning model writes the pool: a reasoning model spends its
|
||||
// budget thinking about a twenty-line list and returns nothing.
|
||||
var chatModel = await opts.getSetting('clinical_assistant.prompt_model', '') || process.env.CLINICAL_ASSISTANT_PROMPT_MODEL || 'openrouter-gpt-4.1-mini';
|
||||
var generated = [];
|
||||
var startedAt = Date.now();
|
||||
// A build that produced nothing used to vanish without a word; now it says
|
||||
|
|
|
|||
|
|
@ -22,7 +22,9 @@ test('clinical assistant starter prompts are Redis or indexed-source backed', ()
|
|||
assert.match(pool, /redisBaseKey \+ ':age:' \+ ageBand/);
|
||||
assert.match(pool, /redisBaseKey \+ ':intent:' \+ intent/);
|
||||
assert.match(pool, /CLINICAL_ASSISTANT_PROMPT_POOL_TARGET, 1000/);
|
||||
assert.match(pool, /CLINICAL_ASSISTANT_PROMPT_POOL_REFRESH_MS, 7 \* 24 \* 60 \* 60 \* 1000/);
|
||||
// Built once, then only from the admin button: no timer unless the environment asks for one.
|
||||
assert.match(pool, /CLINICAL_ASSISTANT_PROMPT_POOL_REFRESH_MS, 0\)/);
|
||||
assert.match(pool, /process\.env\.CLINICAL_ASSISTANT_PROMPT_MODEL \|\| 'openrouter-gpt-4\.1-mini'/);
|
||||
assert.match(route, /loadStoredPromptPool: loadLatestPromptPoolSnapshot/);
|
||||
assert.match(pool, /PEDIATRIC_TAXONOMY/);
|
||||
assert.match(pool, /taxonomyWithQuotas\(target\)/);
|
||||
|
|
|
|||
Loading…
Reference in a new issue