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
19 changes: 0 additions & 19 deletions .github/huggingface/space_readme_header.md

This file was deleted.

58 changes: 0 additions & 58 deletions .github/workflows/sync-hf-space.yml

This file was deleted.

4 changes: 2 additions & 2 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,8 @@ jobs:
with:
enable-cache: true

- name: Sync dependencies (base + dev + gradio)
run: uv sync --extra gradio # so the Gradio GUI is covered by the suite
- name: Sync dependencies (base + dev)
run: uv sync

- name: Tests (pytest)
run: uv run pytest -q
Expand Down
12 changes: 4 additions & 8 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,19 +17,15 @@ save/load a run). Python 3.13, managed with **uv**.

```bash
uv sync # base install (Anthropic, OpenAI, LiteLLM + NiceGUI)
uv sync --extra gradio # + the Gradio GUI
uv sync --extra bertopic # + BERTopic topic backend (heavy)

cp .env.example .env # add provider key(s); loaded automatically
uv run conference-analyzer # NiceGUI GUI on http://localhost:6868
uv run conflens-gradio # Gradio GUI on http://localhost:7860
uv run conference-analyzer --clear-cache # wipe the on-disk cache
```

**Two front-ends, kept in parity:** `app.py` (NiceGUI) and `gradio_app.py`
(Gradio, deployed to Hugging Face). All non-UI logic lives in `view.py` +
`pipeline.py`; when you change a user-facing feature, update **both** GUIs. See
[CLAUDE.md](CLAUDE.md).
The GUI (`app.py`) is a thin **NiceGUI** presentation layer; all non-UI logic
lives in `view.py` + `pipeline.py` — put behaviour changes there.

Docker: `docker compose up --build` (see the README).

Expand Down Expand Up @@ -66,8 +62,8 @@ regexes over heavyweight parsers, small focused modules).

| Area | Module |
|------|--------|
| GUIs (feature parity) | `app.py` (NiceGUI), `gradio_app.py` (Gradio) |
| Shared view logic | `view.py` (filter/sort/highlight/compute_view/exports) |
| UI (NiceGUI) | `app.py` |
| View logic | `view.py` (filter/sort/highlight/compute_view/exports) |
| Exports | `pptx_export.py`, `bibtex.py` |
| Orchestration | `pipeline.py` (`AnalysisConfig`, `run_analysis`) |
| Sources | `sources.py` (registry + `make_source`; `IJCAISource`, `OpenReviewSource`, `PSCCSource`, `DBLPSource`), `scraper.py` (`AnthologyScraper` — also serves EMNLP/NAACL) |
Expand Down
17 changes: 5 additions & 12 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,16 +25,9 @@ repository or its GitHub artifacts:
feature (the `anthropic` provider and `claude-*` model ids in `llm.py`) and
stays — this policy is about tooling attribution, not the app's providers.

## Two front-ends (persistent — keep both maintained)
## Front-end (NiceGUI)

The app ships **two GUIs with feature parity**:

- **NiceGUI** — `conflens/app.py` (console script `conference-analyzer`); run
locally / in Docker.
- **Gradio** — `conflens/gradio_app.py` (console script `conflens-gradio`); this
is the front-end deployed to Hugging Face Spaces.

All non-UI logic (filtering, sorting, highlighting, the computed view, exports)
lives in **`conflens/view.py`** and the pipeline — put behaviour changes there so
both GUIs inherit them. When you add or change a user-facing feature, **update
both `app.py` and `gradio_app.py`** so they stay in parity.
The app has a single **NiceGUI** GUI in `conflens/app.py` (console script
`conference-analyzer`). All non-UI logic (filtering, sorting, highlighting, the
computed view, exports) lives in **`conflens/view.py`** and the pipeline — put
behaviour changes there so the UI stays a thin presentation layer.
53 changes: 4 additions & 49 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,7 @@
[![uv](https://img.shields.io/badge/managed%20by-uv-DE5FE9.svg?logo=uv&logoColor=white)](https://docs.astral.sh/uv/)
[![Built with NiceGUI](https://img.shields.io/badge/UI-NiceGUI-2b6cb0.svg)](https://nicegui.io)

A desktop-style web app — with **two interchangeable front-ends**,
[NiceGUI](https://nicegui.io) (local/Docker) and [Gradio](https://gradio.app)
(deployed to Hugging Face Spaces) — that:
A desktop-style web app (built with [NiceGUI](https://nicegui.io)) that:

1. **Browses** papers from a chosen **source** and retrieves their abstracts:
- the [ACL Anthology](https://aclanthology.org) (default; e.g. `acl-2026`),
Expand Down Expand Up @@ -44,7 +42,7 @@ A desktop-style web app — with **two interchangeable front-ends**,

## Contents

- [Quick start](#quick-start) · [Run with Docker](#run-with-docker) · [Deploy to Hugging Face Spaces](#deploy-to-hugging-face-spaces) · [LLM providers](#llm-providers)
- [Quick start](#quick-start) · [Run with Docker](#run-with-docker) · [LLM providers](#llm-providers)
- [Architecture](#architecture) · [How it works](#how-it-works)
- [Configuration](#configuration-in-the-ui) · [Features](#features)
- [Caching](#caching) · [Cost](#cost) · [BERTopic](#optional-bertopic)
Expand All @@ -57,15 +55,10 @@ Requires Python 3.13+ and [uv](https://docs.astral.sh/uv/).
```bash
uv sync # Claude, OpenAI, LiteLLM work out of the box
cp .env.example .env # then fill in your provider key(s)
uv run conference-analyzer # NiceGUI GUI → http://localhost:6868
uv run conference-analyzer # or: uv run python run.py
```

Prefer **Gradio** (same features; the front-end deployed to Hugging Face)?

```bash
uv sync --extra gradio
uv run conflens-gradio # Gradio GUI → http://localhost:7860
```
Then open <http://localhost:6868>.

Keys are read from `.env` (loaded automatically) or the process environment;
you can also paste a key into the app's **API key** field at runtime.
Expand Down Expand Up @@ -99,44 +92,6 @@ docker run --rm -p 6868:6868 --env-file .env \
To also build the optional BERTopic backend into the image:
`docker build --build-arg EXTRAS="--extra bertopic" -t conference-analyzer .`

### Deploy to Hugging Face Spaces

The **Gradio** front-end is deployed to Hugging Face as a **Gradio SDK Space**
(free CPU tier). HF installs [`requirements.txt`](requirements.txt) and runs
[`space_app.py`](space_app.py), which serves `conflens.gradio_app`. A GitHub
Action mirrors `main` to the Space on every push, so it stays in sync.

**One-time setup:**

1. **Create the Space** — on <https://huggingface.co/new-space>, pick **Gradio →
Blank**, **CPU basic** hardware (this app is CPU-only; ZeroGPU errors with
*"No @spaces.GPU function detected"*), and note its owner + name (e.g.
`your-user/conflens`).
2. **Give GitHub a token** — create a Hugging Face access token with **write**
scope (Settings → Access Tokens) and add it to this GitHub repo as a secret
named **`HF_TOKEN`** (Settings → Secrets and variables → Actions).
3. **Point the action at your Space** *(optional)* — the workflow defaults to
owner `picault` and space `conflens` (the HF username differs from the GitHub
owner). If your Space differs, set repo **variables** `HF_USERNAME` and
`HF_SPACE`.
4. **Add your API keys as *Space* secrets** — in the Space's *Settings →
Variables and secrets*, add whatever your provider needs (e.g.
`ANTHROPIC_API_KEY`, or `OPENAI_API_KEY` / `OPENAI_BASE_URL`; see
[`.env.example`](.env.example)). The app reads them as environment variables.

That's it — push to `main` (or run the **Sync to Hugging Face Space** workflow
manually) and the Space rebuilds. The Space metadata (`sdk: gradio`,
`app_file: space_app.py`, …) lives in
[`.github/huggingface/space_readme_header.md`](.github/huggingface/space_readme_header.md);
the action prepends it to the README it pushes, so the GitHub README stays clean.

> The Space's filesystem is ephemeral, so the on-disk cache resets on rebuild.
> For persistent caching, attach Hugging Face **persistent storage** and set
> `HOME` (or a `--cache-dir`) to point at its `/data` mount.

> The Docker image above still runs the **NiceGUI** app (`0.0.0.0:6868`) for
> local/self-hosted use; the two front-ends share all analysis logic.

### LLM providers

The classifier and topic engine work with three providers, chosen in the UI:
Expand Down
Loading
Loading