跳到正文
GitHub·· 3 小时前AI 评分22

SummarizePaper:用 AI 总结 arXiv 等论文并提供问答助手

summarizepaper/summarizepaper

AI 导读

SummarizePaper 是一个用 AI 总结 arXiv、期刊及 bioRxiv、medRxiv、HAL、OSF、PubMed、Europe PMC 等来源论文的 Web 应用,并提供基于论文全文的问答助手。

正文

A web application that uses AI to summarize academic papers from arXiv, journals and other preprint servers, and provides a virtual assistant 🤖 to answer questions about them. Live at SummarizePaper.com.

Features ✨

  • Summaries of arXiv papers (detailed summary, key points, lay summary, blog-style article) in English and French
  • Papers from journals and other preprint servers too: paste a DOI or a bioRxiv, medRxiv, HAL, OSF (PsyArXiv...), PubMed or Europe PMC link, or search the open-access literature (OpenAlex). As for arXiv, the full text is read only under a license that allows it (CC BY, BY-SA, BY-NC, BY-NC-SA, CC0), otherwise the abstract
  • An AI assistant that answers questions from the full text of the paper, with streamed answers
  • Chat with several papers at once
  • A daily email digest of new papers in the arXiv, bioRxiv and medRxiv categories you follow
  • Premium subscriptions (Stripe) for the most capable model and higher limits
  • BibTeX, RIS and Markdown exports, related papers, PDF export of summaries
  • Summaries rewritten for another reader (a 12-year-old to an expert) or in 16 languages
  • Collections of papers, with a comparison table and their open questions (Premium) and chat with a whole collection
  • Premium tools: press kit with a hype check for journalists, "What did I miss?" (arXiv papers close to a draft that it does not cite), scoop watch (an email the day a new paper comes close to a project in progress), bibliography check (retractions, preprints published since, citations their abstract does not support), what changed between two versions of a paper (and an email when a followed paper gets one), who works on a topic (the groups that publish the most on it, OpenAlex), journal club slides, a conference companion (the talks of a program that matter for one's research), citation alerts, the digest read aloud, papers sent to Zotero with their summaries
  • Rising topics on arXiv (term counts week over week) and weekly letters written like magazine articles

Stack

Django 5.2 served by Daphne (ASGI), Channels websockets over Redis, PostgreSQL on Heroku. Python 3.12 (see .python-version).

Module Role
summarizer/views.py Pages, search, paper page
summarizer/consumers.py Websocket: runs summaries and the assistant
summarizer/assistant.py Questions and detailed summaries over the full paper text
summarizer/paper_source.py Paper text: arXiv HTML first, PDF fallback
summarizer/sources.py Papers from other sources (DOI, bioRxiv, medRxiv, OSF, HAL, Europe PMC, OpenAlex): keys, licenses, metadata, full text, search
summarizer/access.py Client IP, paid status, quotas (never trusts the browser)
summarizer/billing.py Stripe Checkout, Customer Portal, webhook
summarizer/digest.py Daily digest selection, blurbs and emails
summarizer/accounts.py Email login links (also activate new accounts), signup bot checks
summarizer/generated.py Model-written results made in a background thread and polled by the page
summarizer/reading.py, presskit.py Rewrites for another reader or language; press kit
summarizer/questions.py Open questions of a collection
summarizer/library.py, exports.py Collections and their comparison table; BibTeX, RIS, Markdown, Zotero
summarizer/missed.py, citations.py "What did I miss?"; citation alerts (Semantic Scholar)
summarizer/refcheck.py Bibliography check of a .bib (and its .tex)
summarizer/changes.py What changed between two arXiv versions; new version alerts
summarizer/teams.py Who works on a topic: groups by institution, from OpenAlex
summarizer/slides.py Journal club slides of a paper, with its figures under an open license
summarizer/conference.py Conference companion: the talks of a program ranked for a researcher
summarizer/scoops.py Scoop watch: projects in progress compared with each new announcement
summarizer/usage.py AI tokens and cost by task, model, day and user (admin: usage de l’IA)
summarizer/audio.py, trends.py, letters.py Digest read aloud; rising topics; weekly letters

Local setup 💾

python3.12 -m venv venv
venv/bin/pip install -r requirements.txt
export SECRET_KEY=dev OPENAI_KEY=sk-...
venv/bin/python manage.py migrate
venv/bin/python manage.py runserver

Websockets need a Redis on 127.0.0.1:6379 locally (brew services start redis).

Run the tests with venv/bin/python manage.py test summarizer.

Configuration (Heroku config vars)

Variable Purpose
SECRET_KEY Django secret key
ON_HEROKU Enables production settings
DATABASE_URL, REDISCLOUD_URL Set by the Postgres and Redis Cloud add-ons
OPENAI_KEY OpenAI API key
SECRETCMTA SMTP password (outgoing email)
ADS_TOKEN NASA ADS API token, source of the citation alerts' citing papers (Semantic Scholar alone while unset)
S2_API_KEY Optional Semantic Scholar key, raises the rate limit of the citation alerts
OPENALEX_API_KEY Optional, free (openalex.org/settings/api): raises the daily budget of the journal search from $0.10 per IP to $1, and lets us read the full text OpenAlex keeps when publishers refuse scripts (MNRAS, A&A...)
STRIPE_SECRET_KEY, STRIPE_WEBHOOK_SECRET, STRIPE_PRICE_MONTHLY, STRIPE_PRICE_YEARLY Premium subscriptions; Premium stays closed while unset

Premium conversion tracking

The 2026-10-21 code audit prioritised lost Premium intent after signup/activation, pricing and subscribe buttons hidden below the feature list, and unrecoverable Checkout errors. The home hero now links to Premium, the Premium card comes first with its prices and CTA above its features, and signup, Google sign-in and email activation preserve a validated next URL. Stripe errors display a retry message; active subscribers cannot start another purchase.

With UMAMI_WEBSITE_ID enabled, static/summarizer/js/funnel.js sends:

Event Meaning
premium_click, premium_view Homepage/navigation interest, then pricing page
premium_signup, signup_view, signup_submit, signup_error Signup entry, submission attempt or validation error
activation_email_pending Activation instructions displayed; not proof of email delivery or account activation
checkout_start Checkout form submitted, with period monthly/yearly; not proof a Stripe session was created
checkout_error, checkout_cancel, checkout_return Stripe API failure shown, cancellation return, or success return
premium_activated First Premium page rendered with server-confirmed paid access after Checkout started in this browser session

Build separate Umami funnels for anonymous visitors (Premium → signup → Checkout → activation) and existing accounts (Premium → Checkout → activation), split by language and billing period. Returns and submitted forms must never be counted as payments. premium_activated is a browser signal: it can be missed if the visitor never returns, blocks analytics, or activates on another device. Stripe/webhooks and UserPlan remain the subscription source of truth. Compare their totals before drawing conclusions about conversion. No production Umami dashboard or Stripe account was available for this audit; no uplift or abandonment rate has been measured.

Analytics failures do not block forms. Event properties contain only allowlisted language, billing period, placement and tool identifiers; URLs remove login/reset tokens and arbitrary query strings while preserving UTM campaign attribution. Future priorities: measure stage drop-off, then test simpler signup (currently username, email and two password fields) and a shorter benefit-led feature list. Do not remove email verification or bot checks based on an unmeasured assumption.

Verification: python manage.py test summarizer and node --test tests/funnel.test.cjs. French source translations are in locale/fr/LC_MESSAGES/django.po; compile catalogs with python manage.py compilemessages when preparing translated runtime assets.

Research companion homepage

The bilingual homepage groups tools by research task, with free paper search and Daily Digest as entry points. Worked examples are editorial illustrations with original-paper links, not customer results or a live digest. Premium uses the existing cached Stripe monthly price; an unavailable quote is omitted. Existing search routes, canonical URLs and structured data remain.

Additional Umami events: home_search_submit (nonempty search attempt), home_example_click, home_tool_click, paper_result_view (a page containing a completed summary), and digest_configured (shown once after a successful subscription save). Tool links allow only paper, digest, refcheck, missed, scoops; placements allow hero, needs, examples, offer, recent. Research queries, manuscript text and email addresses are never event properties. Measure distinct visitors reaching a result or saving a digest before examining Premium conversion. Result views can recur, and digest configuration is not proof that an email was delivered.

Homepage search now defaults to a combined arXiv and journal/preprint search. Both providers run concurrently, results are interleaved and deduplicated by DOI/arXiv identity, and successful searches are cached for six hours (partial failures for one minute). Partial results carry an explicit notice. Existing source-specific result URLs remain available as optional filters. arXiv IDs, abs/pdf/html links, versions and legacy archive IDs open directly; DOI and other supported identifiers retain the existing resolver. A fresh search from either page searches all sources by default.

Search scope is optional (field=all, author, title, or abstract) and persists through result filters and pagination. Identifiers still take precedence over scope. arXiv uses au: / ti:; OpenAlex uses quoted byline/title filters (see search documentation). Crossref fallback uses query.author / query.title and verifies the requested metadata. Caches include scope and source so author and title searches cannot share unrelated results. Clickable homepage examples fill the field and scope without submitting. Search forms show a translated loading state, prevent repeat submissions and reset after browser back navigation. Verify with node --test tests/funnel.test.cjs tests/home-search.test.cjs and the Django suite.

The results page includes optional year bounds, relevance/newest/oldest ordering, publication type, abstract-only search, ORCID (format and checksum validated), and up to five included and five excluded journals. Journal suggestions use OpenAlex source IDs, display ISSN/publisher for disambiguation, are cached, and share the existing daily search budget. Includes are OR; exclusions are AND. All state is kept in GET parameters and pagination; changing filters starts from page one.

Date and abstract filters are sent to both providers before retrieval. The combined date ordering sorts the returned records across providers. arXiv years refer to submission dates; indexed records use publication dates. Journal, ORCID, published-article and review filters use indexed records, with a visible notice; incompatible explicit arXiv-only requests show validation errors. Crossref retains supported date/order filters during fallback, but never substitutes a broader search for an unsupported abstract/journal/ORCID/type filter. Partial failures remain visible. Results load in provider pages of 25, with a signed continuation backed by cached prior batches. Each click fetches only the next batch, reuses cached batches and deduplicates identities. Up to 20 batches (500 matches per provider) can be loaded per result window; expired windows restart with a notice. Partial provider failures never offer a continuation that would skip the failed batch. Classification, journal assignment and ORCID coverage depend on the indexed metadata.

API references: OpenAlex filters, arXiv API, Crossref filters.

Source abstracts appear directly as short excerpts, with the full abstract expandable. No AI calls are made for previews. Active-filter chips remove only the chosen filter and reset result paging.

Journal club editor and PDF layout

Journal club keeps the generated deck shared and saves each Premium reader's text, notes and layout in a separate Generated(kind='slides_edit') row keyed by user, paper and language. Private results are owner-only and page/save responses are never cached. A revision hash rejects stale-tab saves with HTTP 409; failed requests retain the unsaved editor state. Source figures and credits cannot be replaced by client payloads. No schema migration is needed.

slides.js previews the exact 1280 × 720 canvas, scales it to the screen, allows four figure positions, a 25–70% figure area and three text sizes, and shrinks overflowing text down to 20px before warning. Notes remain outside the slide and never enter the PDF. The PDF button waits for fonts/images and uses the browser's print-to-PDF dialog; slides.css specifies a zero-margin 338.666667 × 190.5mm page (16:9), one slide per page, including when invoked during presentation mode. A print-dialog paper size override may override the CSS page size. Check the final PDF in the target browser.

Validation: python manage.py test summarizer and node --test tests/*.test.cjs.

Saved searches and email watches

Signed, validated search parameters can be saved by a logged-in user; records are private, unique per user and parameter set, and limited to 50 per account. Reopening restores every filter, without old continuation tokens. Users can rename or delete searches and explicitly enable/pause email watches. Free accounts may run one watch, Premium five; after a downgrade only the earliest watches within the current limit run, with their status shown in the management page.

Activation/resumption persists the opt-in immediately, without source requests in the web process. The hourly worker retries initialization until every required source responds, then snapshots the latest 50 matches as a baseline and sends no historical email. The UI shows initialization pending until then. Daily/weekly checks compare that bounded latest-match window with seen DOI/arXiv aliases. A message contains up to ten unseen matches; coverage is explicitly bounded, not an exhaustive literature alert. No summaries are generated by the watcher. Suppressed addresses and inactive users are skipped. A database lease prevents overlapping workers from delivering the same check concurrently; failures leave delivery state unchanged for retry. Successful mail advances the seen set and schedule. A signed unsubscribe URL opens a confirmation; only POST pauses the watch, so email prefetching is safe.

Umami receives saved_search_created and search_watch_enabled once from server-confirmed save/enable actions, and search_more_click for continuation clicks. No query, filter, source ID, ORCID, saved-search ID or manuscript text is included in these event properties.

The existing hourly send_digest command runs search watches last, using only its remaining email budget (and at most ten checks per run). --dry-run and --user never send search watches. There is no new Heroku Scheduler job. The release migration creates SavedSearch; it activates no existing user. Validation: python manage.py test summarizer and node --test tests/funnel.test.cjs tests/home-search.test.cjs.

Deployment

git push heroku master. The release phase of the Procfile applies migrations.

  • Hourly job (Heroku Scheduler): python manage.py send_digest. It sends the digests that are due, then counts the day's terms for the rising topics, writes the weekly topics and letters, and sends scoop alerts, citation alerts, new version alerts and letters within what is left of the hourly email budget.
  • Stripe: webhook endpoint https://www.summarizepaper.com/stripe/webhook/ with the events checkout.session.completed, customer.subscription.created, customer.subscription.updated and customer.subscription.deleted.

Contributors :octocat:

Developed by ✨ Quentin Kral ✨. Questions or suggestions are welcome.

License 📃

MIT License, see the LICENSE file. 📋

来源:GitHub · github.com