This system automatically fetches Google Scholar alert emails from Gmail, parses them, scores articles for relevance using an LLM, and generates a Markdown digest report.
- Gmail Integration: Fetches new Scholar alerts since the last run.
- HTML Parsing: Extracts article titles, links, and summaries from email content.
- Deduplication: Avoids processing the same article multiple times using a title hash.
- LLM Scoring: Uses Langchain with configurable LLM providers (OpenAI, Google Gemini) to score articles based on relevance (High, Medium, Low) defined by your interests. Falls back to a MockLLM if API keys are not set.
- Configurable: All key settings (keywords, LLM parameters, prompt templates, language) are managed in
config.yml. - Storage: Saves article data to CSV and optionally SQLite for persistence and easy access.
- Reporting: Generates a daily Markdown report of relevant articles, categorized by score.
- Optional Enrichment: Can fetch full text snippets for highly relevant articles (disabled by default).
- CLI Interface: Uses Typer for easy command-line operations (
fetch,report,update-ts).
scholar_digest/
│ config.yml # User configuration (keywords, prompts, LLM settings)
│ last_run.txt # Timestamp of the last successful email fetch (Unix seconds)
│
├─ cli.py # Typer CLI application entry point
├─ mail_fetcher.py # Gmail API interaction for fetching emails
├─ parser.py # HTML parsing logic for Scholar emails
├─ storage.py # Data persistence (CSV/SQLite), deduplication, timestamp management
├─ scorer.py # LLM scoring (OpenAI, Google) and optional web content enrichment
├─ report_builder.py # Markdown/HTML report generation using Jinja2
└─ templates/
└─ report_template.md.j2 # Default Jinja2 template for the Markdown report
└─ README.md # This file
.gitignore # Specifies intentionally untracked files (e.g., credentials)
requirements.txt # Python package dependencies
credentials.json # Google API credentials for Gmail (SHOULD BE IN .gitignore)
token.json # Google API token for Gmail (SHOULD BE IN .gitignore, generated on first run)
reports/ # Default directory for generated reports and data files (CSV/DB)
-
Clone the repository (or create files as per above).
-
Install Dependencies:
python -m venv venv source venv/bin/activate # On Windows: venv\Scripts\activate pip install -r requirements.txt
-
Google API Credentials (for Gmail):
- Go to the Google Cloud Console.
- Create a new project or select an existing one.
- Enable the "Gmail API".
- Create credentials for a "Desktop app" for an OAuth application. You will get a json file to download.
- Download the
credentials.jsonfile (The download name will be different, but with inside it will store the app's identifier and key) and place it in the root directory of this project (alongsiderequirements.txt). - Important: Ensure
credentials.jsonandtoken.json(will be generated on first run for Gmail) are listed in your.gitignorefile. The required scopes for Gmail arehttps://www.googleapis.com/auth/gmail.readonly.
-
LLM API Keys (OpenAI and/or Google AI): To use actual LLM scoring, you need to set the respective API keys as environment variables:
- For OpenAI: Set the
OPENAI_API_KEYenvironment variable.(On Windows, useexport OPENAI_API_KEY="your_openai_api_key"
set OPENAI_API_KEY=your_openai_api_keyin Command Prompt or$env:OPENAI_API_KEY="your_openai_api_key"in PowerShell). - For Google AI (Gemini models): Set the
GOOGLE_API_KEYenvironment variable.(Adjust for your OS as above).export GOOGLE_API_KEY="your_google_ai_api_key"
- If these keys are not set, the system will fall back to using the
MockChatLLMfor scoring, which provides placeholder scores.
- For OpenAI: Set the
-
Configure
scholar_digest/config.yml: Openscholar_digest/config.ymland customize it to your needs:language: For prompts (e.g.,en,zh). (Seems not integrated, better specify it in prompt)prompt_template: The template for the LLM to score articles. It must request JSON output with{"score":"High|Medium|Low","reason":"..."}.keywords:include: List of keywords that indicate relevance. (will be provided as part of information for llm)exclude: List of keywords that indicate irrelevance (will auto-score as Low).
llm:model: Specify the LLM provider and model name using the format"provider:model_name".- Examples:
"openai:gpt-4o","openai:gpt-3.5-turbo","google:gemini-1.5-flash-latest"(The model name should be compatible with ChatOpenAI or Google AI, depending on provider). - If an unsupported provider or format is used (and API keys are set), an error will occur.
- For testing without API calls, you can use
"mock:some-name"if you uncomment the MockLLM part inget_llm_instanceinscorer.py(currently, it falls back to MockLLM automatically if real LLM init fails).
- Examples:
temperature: LLM temperature setting.
scoring:high_threshold: The string value from LLM output considered "High" relevance.medium_threshold: The string value for "Medium" relevance.
enrichment:enable_web_article: Set totrueto attempt fetching a snippet of the full article text from the web for highly-rated articles. Defaults tofalse.
output:report_dir: Directory where reports and data files (CSV, SQLite DB) will be stored. Defaults toreportsin the root directory.
Ensure your virtual environment is activated and API keys are set if you want to use actual LLMs.
Run commands from the root directory of the project (where requirements.txt is).
-
Fetch new emails, process, and generate a report (recommended): This command reads the
last_run.txttimestamp to fetch only new emails since the last execution. On the first run (or iflast_run.txtis missing/empty), it will attempt to fetch all emails with thelabel:scholar-alerts.python -m scholar_digest.cli fetch
-
Fetch emails from a specific start date/time: You can specify a start time using either a ISO 8601 date/datetime string or a Unix timestamp.
python -m scholar_digest.cli fetch --since 2023-10-01 python -m scholar_digest.cli fetch --since 2023-10-01T10:00:00 python -m scholar_digest.cli fetch --since 1696140000
-
Generate a report from already fetched and scored data: This command does not fetch new emails. It uses the existing data in
reports/scholar_articles.csv.python -m scholar_digest.cli report
-
Manually update the last run timestamp: Sets
last_run.txtto the current time or a specified value.python -m scholar_digest.cli update-ts python -m scholar_digest.cli update-ts --value 2023-10-05T12:00:00 python -m scholar_digest.cli update-ts --value 1696492800
On the first run of any command that requires Gmail access (like fetch), your web browser will open, prompting you to log in to your Google account and authorize the application to access your Gmail data (read-only by default).
After successful authentication, a token.json file will be created in the root directory. This token will be used for subsequent runs, so you won't need to re-authenticate every time for Gmail access, unless the token expires or scopes change.
- The
scorer.pynow attempts to initialize an LLM based on yourconfig.yml(llm.modelfield). - Ensure
langchain-openaiand/orlangchain-google-genaiare inrequirements.txtand installed. - If
OPENAI_API_KEY(for OpenAI models) orGOOGLE_API_KEY(for Google models) are not set in your environment, or if the specified model cannot be loaded, the system will print an error and fall back to usingMockChatLLMfor that run. This mock LLM provides deterministic but very basic scoring based on keywords and is not suitable for production use. - The
google:gemini-promodel (and other Google models) require theGOOGLE_API_KEY.
- LLM Integration:
scholar_digest/scorer.pyhandles OpenAI and Google. You can extendget_llm_instanceto support other Langchain providers. - Report Template: Edit
scholar_digest/templates/report_template.md.j2to change the structure or content of the Markdown report. - Storage: The system uses CSV by default and can also use SQLite. Configure this in
storage.pyif needed.
Each module (mail_fetcher.py, parser.py, storage.py, scorer.py, report_builder.py) has an if __name__ == "__main__": block with example usage or basic tests. You can run them individually for development and testing, e.g.:
python scholar_digest/parser.py
# For scorer.py, ensure API keys are set or expect fallback to MockLLM
python scholar_digest/scorer.py (You might need to adjust paths or ensure credentials.json (for Gmail) is accessible and config.yml is populated for some of these direct runs).
- Repetition report generation (limited to current run, not historical).
- Full abstract information gathering (currently will use only the summary from the email).
- The test of web enrichment function
- Other source integration (e.g., arXiv, PubMed).