BioScan Museo exposes two chat endpoints that let visitors ask natural-language questions about any species in the collection. Both endpoints combine a structured species fact-sheet from the database, a vector-search pass over museum documents (ChromaDB), and an Ollama-powered LLM. The non-streamingDocumentation Index
Fetch the complete documentation index at: https://mintlify.com/GustavoNightmare/InformacionMuseo/llms.txt
Use this file to discover all available pages before exploring further.
/api/chat endpoint is stateless and requires no login; the streaming /api/chat_stream endpoint is session-aware, personalises answers with the visitor’s tour history, and persists each exchange as a ChatTurn record. A third endpoint, /api/especies/comparar/analysis, generates a side-by-side taxonomic analysis for any two related species.
POST /api/chat
Send a single question about a species and receive a complete plain-text answer in one JSON response. The endpoint resolves question scope (specimen, general, or mixed) via classify_question_scope() in rag.py and builds a structured context with build_structured_context() before querying Ollama. If the user is authenticated, recent visit history is included in the context via build_tour_memory_context().
Authentication: None required. When the caller is authenticated, the response is enriched with personalised tour context.
Request body
The internal species ID (same as
qr_id). Must match ^[a-z0-9-_]+$. Sanitised server-side by sanitize_id() and validated against ID_RE.The visitor’s question. Must be a non-empty string. Leading/trailing whitespace is stripped.
Response
true on success, false on any error.The LLM-generated plain-text answer. Present only when
ok is true.Human-readable error description. Present only when
ok is false.HTTP status codes
| Code | Meaning |
|---|---|
200 | Success — answer is populated. |
400 | species_id failed validation or message is empty. |
404 | No species found for the given species_id. |
500 | LLM call failed — error contains the exception message. |
Example
POST /api/chat_stream
Same RAG pipeline as/api/chat, but streams Ollama’s response token-by-token as a plain-text text/plain HTTP stream. This endpoint is session-aware: it reads the last exchange from ChatTurn to handle short follow-up questions (e.g., “¿por qué?”), builds a personalised tour-memory block with build_tour_memory_context(), and saves the completed exchange back to ChatTurn once streaming finishes.
Before reaching the LLM, the endpoint checks maybe_build_direct_chat_answer(). If the question matches a known pattern — such as asking how many species the museum has or requesting a comparison with previously visited species — a direct answer is returned immediately without calling Ollama.
Authentication: Login required. Returns HTTP 401 with the plain-text body ERROR: login requerido if the caller is not authenticated.
Request body
The target species ID. Sanitised and validated against
^[a-z0-9-_]+$ (same rules as /api/chat).The visitor’s question. Must be a non-empty string.
Response
On success the endpoint returns200 OK with Content-Type: text/plain; charset=utf-8 and streams the answer in plain text chunks. There are no SSE envelopes — each chunk is raw text that can be appended directly to the UI.
On error before streaming starts, the response is still text/plain with the appropriate HTTP status:
| Code | Body prefix | Cause |
|---|---|---|
400 | ERROR: species_id inválido | species_id failed the ID_RE check. |
400 | ERROR: mensaje vacío | message was empty or missing. |
401 | ERROR: login requerido | Caller is not authenticated. |
404 | ERROR: Especie no encontrada | No species matched the given ID. |
curl example
JavaScript fetch example (ReadableStream)
The streaming endpoint persists the full conversation to the database. After the stream closes, both the visitor’s message and the assistant’s complete response are saved as
ChatTurn records linked to the authenticated user and the species. The session retains the last 60 turns per user per species; older turns are pruned automatically.GET /api/especies/comparar/analysis
Returns a structured JSON comparison between two taxonomically related species. The comparison is generated by Ollama using both species’ structured fact-sheets. If the LLM call fails or returns unparseable JSON, the endpoint falls back tobuild_basic_comparison_fallback(), which derives differences and similarities directly from the database fields.
Authentication: None required.
Query parameters
The
qr_id of the first species (species A). Sanitised and validated against ^[a-z0-9-_]+$.The
qr_id of the second species (species B). Sanitised and validated against ^[a-z0-9-_]+$. Must be different from a.familia or the same orden (case-insensitive comparison). If they do not, the endpoint returns 400.
Response
true when a valid comparison was produced.The structured comparison object.
true when the analysis was produced by the LLM, false when the fallback logic was used.Error description. Present only when
ok is false.HTTP status codes
| Code | Cause |
|---|---|
200 | Comparison produced successfully. |
400 | One or both species IDs are invalid, the same, not found, or not taxonomically related. |