Files
bookshelf/config/models.default.yaml
Petr Polezhaev b94f222c96 Add per-request AI logging, DB batch queue, WS entity updates, and UI polish
- log_thread.py: thread-safe ContextVar bridge so executor threads can log
  individual LLM calls and archive searches back to the event loop
- ai_log.py: init_thread_logging(), notify_entity_update(); WS now pushes
  entity_update messages when book data changes after any plugin or batch run
- batch.py: replace batch_pending.json with batch_queue SQLite table;
  run_batch_consumer() reads queue dynamically so new books can be added
  while batch is running; add_to_queue() deduplicates
- migrate.py: fix _migrate_v1 (clear-on-startup bug); add _migrate_v2 for
  batch_queue table
- _client.py / archive.py / identification.py: wrap each LLM API call and
  archive search with log_thread start/finish entries
- api.py: POST /api/batch returns {already_running, added}; notify_entity_update
  after identify pipeline
- models.default.yaml: strengthen ai_identify confidence-scoring instructions;
  warn against placeholder data
- detail-render.js: book log entries show clickable ID + spine thumbnail;
  book spine/title images open full-screen popup
- events.js: batch-start handles already_running+added; open-img-popup action
- init.js: entity_update WS handler; image popup close listeners
- overlays.css / index.html: full-screen image popup overlay
- eslint.config.js: add new globals; fix no-redeclare/no-unused-vars for
  multi-file global architecture; all lint errors resolved

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-11 12:10:54 +03:00

75 lines
4.0 KiB
YAML

# AI model configurations — each model references a credential and provides
# the model string, optional openrouter routing (extra_body), and the prompt.
# ${OUTPUT_FORMAT} is injected by the plugin from its hardcoded schema constant.
# Override individual models in models.user.yaml.
models:
vl_detect_shelves:
credentials: openrouter
model: "google/gemini-flash-1.5"
prompt: |
# ${OUTPUT_FORMAT} — JSON schema injected by BoundaryDetectorShelvesPlugin
Look at this photo of a bookcase/shelf unit.
Count the number of horizontal shelves visible.
For each interior boundary between adjacent shelves, give its vertical position
as a fraction 0-1 (0=top of image, 1=bottom). Do NOT include 0 or 1 themselves.
Return ONLY valid JSON, no explanation:
${OUTPUT_FORMAT}
vl_detect_books:
credentials: openrouter
model: "google/gemini-flash-1.5"
prompt: |
# ${OUTPUT_FORMAT} — JSON schema injected by BoundaryDetectorBooksPlugin
Look at this shelf photo. Identify every book spine visible left-to-right.
For each interior boundary between adjacent books, give its horizontal position
as a fraction 0-1 (0=left edge of image, 1=right edge). Do NOT include 0 or 1.
Return ONLY valid JSON, no explanation:
${OUTPUT_FORMAT}
vl_recognize:
credentials: openrouter
model: "google/gemini-flash-1.5"
prompt: |
# ${OUTPUT_FORMAT} — JSON schema injected by TextRecognizerPlugin
Look at this book spine image. Read all visible text exactly as it appears,
preserving line breaks between distinct text blocks.
Then use visual cues (font size, position, layout) to identify which part is the title,
author, publisher, year, and any other notable text.
Return ONLY valid JSON, no explanation:
${OUTPUT_FORMAT}
ai_identify:
credentials: openrouter
model: "google/gemini-flash-1.5"
prompt: |
# ${RAW_TEXT} — text read from the book spine (multi-line)
# ${ARCHIVE_RESULTS} — JSON array of candidate records from library archives
# ${OUTPUT_FORMAT} — JSON schema injected by BookIdentifierPlugin
Text read from the book spine:
${RAW_TEXT}
Archive search results (may be empty):
${ARCHIVE_RESULTS}
Your task:
1. Search the web for this book if needed to find additional information.
2. Combine the spine text, archive results, and your web search into identification candidates.
3. Collapse candidates that are clearly the same book (same title + author + year + publisher) into one entry, listing all contributing sources.
4. Rank candidates by confidence (highest first). Assign a score 0.0-1.0.
5. Remove any candidates you believe are irrelevant or clearly wrong.
IMPORTANT — confidence scoring rules:
- The score must reflect how well the found information matches the spine text and recognized data.
- If the only available evidence is a title with no author, year, publisher, or corroborating archive results, the score must not exceed 0.5.
- Base confidence on: quality of spine text match, number of matching fields, archive result corroboration, and completeness of the identified record.
- A record with title + author + year that appears in multiple archive sources warrants a high score; a record with only a guessed title warrants a low score.
IMPORTANT — output format rules:
- The JSON schema below is a format specification only. Do NOT use it as a source of example data.
- Do NOT return placeholder values such as "The Great Gatsby", "Unknown Author", "Example Publisher", or any other generic example text unless that exact text literally appears on the spine.
- Return only real books that could plausibly match what is shown on this spine.
- If you cannot identify the book with reasonable confidence, return an empty array [].
Return ONLY valid JSON matching the schema below, no explanation:
${OUTPUT_FORMAT}