Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 1 addition & 3 deletions .dockerignore
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,4 @@ chroma_db
legacy
tests
docs
components
styles
utils
web
6 changes: 3 additions & 3 deletions DEPLOY.md
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ You create every account and paste every secret yourself. Nothing secret goes in
| Branch | `main` |
| Region | **Frankfurt (EU Central)** |
| Instance type | **Free** |
| Dockerfile Path (Advanced) | `Dockerfile.api` (the default `./Dockerfile` builds the Streamlit app instead) |
| Dockerfile Path (Advanced) | `Dockerfile.api` |
| Docker Build Context | `.` |
| Health Check Path (Advanced) | `/ping` |
| Auto-Deploy | On Commit |
Expand Down Expand Up @@ -140,7 +140,7 @@ without it, all visitors would share one rate limit.
|---|---|
| Repository | this repository |
| Branch | `main` |
| Main file path | `app.py` |
| Main file path | `legacy/streamlit/app.py` |
| App URL | a short name, e.g. `floatchat` |

4. Open **Advanced settings**: choose Python **3.11** or newer, and paste into **Secrets**:
Expand All @@ -150,7 +150,7 @@ without it, all visitors would share one rate limit.
FRONTEND_TOKEN = "<the same secret as on Render>"
```

5. Click **Deploy**. Streamlit installs `requirements.txt` (frontend packages only) and starts the app in a few
5. Click **Deploy**. Streamlit installs `legacy/streamlit/requirements.txt` (frontend packages only) and starts the app in a few
minutes. The sidebar should show green dots for PostgreSQL, the vector index and the LLM.

## Troubleshooting
Expand Down
Binary file removed components/__pycache__/__init__.cpython-313.pyc
Binary file not shown.
Binary file removed components/__pycache__/api_client.cpython-313.pyc
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file removed components/__pycache__/data_fetcher.cpython-313.pyc
Binary file not shown.
Binary file removed components/__pycache__/data_manager.cpython-313.pyc
Binary file not shown.
Binary file removed components/__pycache__/data_sampler.cpython-313.pyc
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file removed components/__pycache__/user_feedback.cpython-313.pyc
Binary file not shown.
15 changes: 9 additions & 6 deletions docker-compose.yml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# One-command local stack: docker compose up --build
# App: http://localhost:8501 API docs: http://localhost:8000/docs
# Web app: http://localhost:3000 API docs: http://localhost:8000/docs
services:
db:
image: pgvector/pgvector:pg16
Expand Down Expand Up @@ -32,7 +32,7 @@ services:
ADMIN_DATABASE_URL: postgresql+psycopg://floatchat:floatchat@db:5432/argo
DATABASE_URL: postgresql+psycopg://floatchat_reader:local-reader-password@db:5432/argo
READER_PASSWORD: local-reader-password
ALLOWED_ORIGINS: http://localhost:8501,http://localhost:3000
ALLOWED_ORIGINS: http://localhost:3000
ports:
- "8000:8000"
extra_hosts:
Expand All @@ -41,12 +41,15 @@ services:
db:
condition: service_healthy

frontend:
build: .
web:
build:
context: ./web
args:
NEXT_PUBLIC_API_URL: http://localhost:8000 # what your browser uses
environment:
BACKEND_URL: http://backend:8000
API_URL_INTERNAL: http://backend:8000 # what the web server uses inside Docker
ports:
- "8501:8501"
- "3000:3000"
depends_on:
- backend

Expand Down
Binary file added docs/screenshots/web-chat-search.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/screenshots/web-chat-sql.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/screenshots/web-float.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/screenshots/web-landing.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
3 changes: 2 additions & 1 deletion floatchat/answer.py
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,8 @@ def _analytical_answer(route: Route, agent: SqlAgent, writer: _Writer, step) ->
writer.write(f"**{title}**\n\n{format_results_for_display(df, intent)}")
insight = writer.llm(
f"Question: {route.question}\n\nSQL result (first rows):\n{df.head(15).to_string(index=False)}\n\n"
"In 2-3 sentences, explain the main oceanographic pattern in this result.",
"In 2-3 sentences of plain prose, explain the main oceanographic pattern in this result. Do not use a list, "
"table or heading, and do not restate the rows one by one.",
prefix="\n\n**What this means:** ",
)
return {
Expand Down
2 changes: 1 addition & 1 deletion floatchat/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ def _sqlalchemy_url(value: str) -> str:
FRONTEND_TOKEN = os.getenv("FRONTEND_TOKEN", "")
ALLOWED_ORIGINS = [
origin.strip()
for origin in os.getenv("ALLOWED_ORIGINS", "http://localhost:3000,http://localhost:8501").split(",")
for origin in os.getenv("ALLOWED_ORIGINS", "http://localhost:3000").split(",")
if origin.strip()
]

Expand Down
5 changes: 3 additions & 2 deletions floatchat/llm.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ def is_configured() -> bool:
return True


# Reasoning models (such as gpt-oss) spend part of max_tokens thinking before they answer, so the limits leave room
def _payload(prompt: str, system: str | None, temperature: float, max_tokens: int, json_mode: bool,
stream: bool = False) -> dict:
messages = [{"role": "system", "content": system}] if system else []
Expand Down Expand Up @@ -58,7 +59,7 @@ def _post(payload: dict, stream: bool = False):
_sleep(min(wait, MAX_RETRY_WAIT))


def chat(prompt: str, system: str | None = None, temperature: float = 0.2, max_tokens: int = 600,
def chat(prompt: str, system: str | None = None, temperature: float = 0.2, max_tokens: int = 1200,
json_mode: bool = False) -> str | None:
if not is_configured():
return None
Expand All @@ -71,7 +72,7 @@ def chat(prompt: str, system: str | None = None, temperature: float = 0.2, max_t


def chat_stream(prompt: str, system: str | None = None, temperature: float = 0.2,
max_tokens: int = 600) -> Iterator[str]:
max_tokens: int = 1200) -> Iterator[str]:
"""Yield the answer text as the LLM writes it; yields nothing if no LLM is available or the call fails."""
if not is_configured():
return
Expand Down
2 changes: 1 addition & 1 deletion floatchat/router.py
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ def _prompt(question: str, history: list[dict]) -> str:


def llm_route(question: str, history: list[dict], chat) -> Route | None:
reply = chat(_prompt(question, history or []), temperature=0.0, max_tokens=300, json_mode=True)
reply = chat(_prompt(question, history or []), temperature=0.0, max_tokens=600, json_mode=True)
if not reply:
return None
try:
Expand Down
File renamed without changes.
File renamed without changes.
15 changes: 15 additions & 0 deletions legacy/streamlit/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# Retired Streamlit apps

FloatChat's frontend is now the Next.js app in [`web/`](../../web). These are kept for reference:

- `app.py`: the interim Streamlit app that served as the showcase before the web app (Phases 1 and 2). It still works
against the API:

```bash
pip install -r legacy/streamlit/requirements.txt
BACKEND_URL=http://localhost:8000 streamlit run legacy/streamlit/app.py
```

On a hosted deployment it passes each visitor's IP with a shared `FRONTEND_TOKEN`, which the API still accepts.
- `streamlit_app.py`, `components/`, `styles/`, `utils/`: an earlier experimental dashboard
(see `README_DASHBOARD.md`), with its tests in `tests/dashboard/`.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
[tool.ruff]
line-length = 120
target-version = "py311"
extend-exclude = ["legacy", "components", "styles", "utils", "tests/dashboard", "streamlit_app.py", "dashboard_config.py", "app.py"]
extend-exclude = ["legacy", "web"]

[tool.ruff.lint]
select = ["E", "F", "I", "B"]
Expand Down
Loading
Loading