Files
WoMenQuNaJu/MeetSpot/CLAUDE.md
2026-02-04 16:11:55 +08:00

9.1 KiB

CLAUDE.md

This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.

Project Overview

MeetSpot is an AI Agent for multi-person meeting point recommendations. Users provide locations and requirements; the Agent calculates the geographic center and recommends optimal venues. Built with FastAPI and Python 3.11+, uses Amap (Gaode Map) API for geocoding/POI search, and DeepSeek/GPT-4o-mini for semantic scoring.

Live Demo: https://meetspot-irq2.onrender.com

Quick Reference

# Environment
conda activate meetspot                  # Or: source venv/bin/activate

# Development
uvicorn api.index:app --reload           # Preferred for iteration
python web_server.py                     # Full stack with auto env detection

# Test the main endpoint
curl -X POST "http://127.0.0.1:8000/api/find_meetspot" \
  -H "Content-Type: application/json" \
  -d '{"locations": ["北京大学", "清华大学"], "keywords": "咖啡馆"}'

# Testing
pytest tests/ -v                         # Full suite
pytest tests/test_file.py::test_name -v  # Single test
pytest --cov=app tests/                  # Coverage (target: 80%)
python tests/test_seo.py http://localhost:8000  # SEO validation (standalone)

# Quality gates (run before PRs)
black . && ruff check . && mypy app/

# Postmortem regression check (optional, runs in CI)
python tools/postmortem_check.py         # Check for known issue patterns

Key URLs: Main UI (/), API docs (/docs), Health (/health)

Repo Rules

  • Follow AGENTS.md for repo-local guidelines (style, structure, what not to commit). In particular: runtime-generated files under workspace/js_src/ must not be committed.
  • There are no Cursor/Copilot rule files in this repo (no .cursorrules, no .cursor/rules/, no .github/copilot-instructions.md).

Environment Setup

Conda: conda env create -f environment.yml && conda activate meetspot (env name is meetspot, not meetspot-dev) Pip: python3.11 -m venv venv && source venv/bin/activate && pip install -r requirements.txt

Required Environment Variables:

  • AMAP_API_KEY - Gaode Map API key (required)
  • AMAP_SECURITY_JS_CODE - JS security code for frontend map
  • LLM_API_KEY - DeepSeek/OpenAI API key (for AI chat and LLM scoring)
  • LLM_API_BASE - API base URL (default: https://newapi.deepwisdom.ai/v1)
  • LLM_MODEL - Model name (default: deepseek-chat)

Local Config: Copy config/config.toml.example to config/config.toml and fill in API keys. Alternatively, create a .env file with the environment variables above.

Architecture

Request Flow

POST /api/find_meetspot
        ↓
Complexity Router (assess_request_complexity)
        ↓
Rule+LLM Mode (Agent mode disabled for memory savings on free tier)
        ↓
5-Step Pipeline: Geocode → Center Calc → POI Search → Ranking → HTML Gen

Complexity scoring: +10/location, +15 for complex keywords, +10 for special requirements. Currently all requests use Rule+LLM mode since Agent mode is disabled (agent_available = False in api/index.py).

Entry Points

  • web_server.py - Main entry, auto-detects production vs development
  • api/index.py - FastAPI app with all endpoints, middleware, and request handling

Three-Tier Configuration (Graceful Degradation)

Mode Trigger What Works
Full config/config.toml exists All features, TOML-based config
Simplified RAILWAY_ENVIRONMENT set Uses app/config_simple.py
Minimal Only AMAP_API_KEY env var MinimalConfig class in api/index.py, basic recommendations only

Core Components

app/tool/meetspot_recommender.py    # Main recommendation engine (CafeRecommender class)
  |- university_mapping dict        # 45 abbreviations (e.g., "北大" -> "北京市海淀区北京大学")
  |- landmark_mapping dict          # 45 city landmarks (e.g., "陆家嘴" -> "上海市浦东新区陆家嘴")
  |- PLACE_TYPE_CONFIG dict         # 12 venue themes with colors, icons
  |- _rank_places()                 # 100-point scoring algorithm
  |- _generate_html_content()       # Standalone HTML with Amap JS API
  |- geocode_cache (max 30)         # LRU-style address cache (reduced for free tier)
  |- poi_cache (max 15)             # LRU-style POI cache (reduced for free tier)

app/design_tokens.py                # WCAG AA color palette, CSS generation
api/routers/seo_pages.py            # SEO landing pages

LLM Scoring (Agent Mode)

When Agent Mode is enabled, final venue scores blend rule-based and LLM semantic analysis:

Final Score = Rule Score * 0.4 + LLM Score * 0.6

Agent Mode is currently disabled (agent_available = False) to conserve memory on free hosting tiers.

Data Flow

1. Address enhancement (90+ university/landmark mappings)
2. Geocoding via Amap API (with retry + rate limiting)
3. Center point calculation (spherical geometry)
4. POI search (concurrent for multiple keywords)
   Fallback: tries 餐厅->咖啡馆->商场->美食, then expands to 50km
5. Ranking with multi-scenario balancing (max 8 venues)
6. HTML generation -> workspace/js_src/

Optional Components

Database layer (app/db/, app/models/) is optional - core recommendation works without it. Used for auth/social features with SQLite + aiosqlite.

Experimental agent endpoint (/api/find_meetspot_agent) requires OpenManus framework - not production-ready.

Key Patterns

Ranking Algorithm

Edit _rank_places() in meetspot_recommender.py:

  • Base: 30 points (rating x 6)
  • Popularity: 20 points (log-scaled reviews)
  • Distance: 25 points (500m = full score, decays)
  • Scenario: 15 points (keyword match)
  • Requirements: 10 points (parking/quiet/business)

Distance Filtering

Two-stage distance handling in meetspot_recommender.py:

  1. POI Search: Amap API radius parameter (hardcoded 5000m, fallback to 50000m)
  2. Post-filter: max_distance parameter in _rank_places() (default 100km, in meters)

The max_distance filter applies after POI retrieval during ranking. To change search radius, modify radius=5000 in _search_places() calls around lines 556-643.

Brand Knowledge Base

BRAND_FEATURES dict in meetspot_recommender.py contains 50+ brand profiles (Starbucks, Haidilao, etc.) with feature scores (0.0-1.0) for: quiet, WiFi, business, parking, child-friendly, 24h. Used in requirements matching - brands scoring >=0.7 satisfy the requirement. Place types prefixed with _ (e.g., _library) provide defaults.

Adding Address Mappings

Two sources for address resolution:

  1. External file: data/address_aliases.json - JSON file with university_aliases and landmark_aliases dicts. Preferred for new mappings.
  2. Internal dicts: university_mapping and landmark_mapping in _enhance_address() method of meetspot_recommender.py. Use for mappings requiring city prefixes (prevents cross-city geocoding errors).

Adding Venue Themes

Add entry to PLACE_TYPE_CONFIG with: Chinese name, Boxicons icons, 6 color values.

Postmortem System

Automated regression prevention system that tracks historical fixes and warns when code changes might reintroduce past bugs.

Structure

postmortem/
  PM-2025-001.yaml ... PM-2026-xxx.yaml  # Historical fix documentation
tools/
  postmortem_init.py     # Generate initial knowledge base from git history
  postmortem_check.py    # Check code changes against known patterns
  postmortem_generate.py # Generate postmortem for a single commit

CI Integration

  • postmortem-check.yml: Runs on PRs, warns if changes match known issue patterns
  • postmortem-update.yml: Auto-generates postmortem when fix: commits merge to main

Adding New Postmortems

When fixing a bug, the CI will auto-generate a postmortem. For manual creation:

python tools/postmortem_generate.py <commit-hash>

Each postmortem YAML contains triggers (file patterns, function names, regex, keywords) that enable multi-dimensional pattern matching.

Debugging

Issue Solution
未找到AMAP_API_KEY Set environment variable
Import errors in production Check MinimalConfig fallback
Wrong city geocoding Add to landmark_mapping with city prefix
Empty POI results Fallback mechanism handles this automatically
Render OOM (512MB) Caches are reduced (30/15 limits); Agent mode disabled
Render service down Trigger redeploy: git commit --allow-empty -m "trigger redeploy" && git push

Logging: Uses loguru via app/logger.py. /health endpoint shows config status.

Deployment

Hosted on Render free tier (512MB RAM, cold starts after 15min idle).

Redeploy: Push to main branch triggers auto-deploy. For manual restart without code changes:

git commit --allow-empty -m "chore: trigger redeploy" && git push origin main

Generated artifacts: HTML files in workspace/js_src/ are runtime-generated and should not be committed.

Code Style

  • Python: 4-space indent, type hints, snake_case functions, PascalCase classes
  • CSS: BEM-like (meetspot-header__title), colors from design_tokens.py
  • Commits: Conventional Commits (feat:, fix:, docs:)