LocalMate / docs /API_REFERENCE.md
Cuong2004's picture
fix intent and add plan
51ba917

LocalMate API Documentation

Base URL: https://huggingface.co/proxy/cuong2004-localmate.hf.space/api/v1
Swagger UI: /docs | ReDoc: /redoc
Version: 0.3.0


📋 Table of Contents

  1. Chat API
  2. User Profile API
  3. Itineraries API
  4. Trip Planner API
  5. Utility Endpoints
  6. Models

Chat API

POST /chat

Main endpoint for interacting with the AI assistant.

Request:

{
  "message": "Quán cafe view đẹp gần Mỹ Khê",
  "user_id": "user_123",
  "session_id": "default",
  "provider": "MegaLLM",
  "model": "deepseek-ai/deepseek-v3.1-terminus",
  "image_url": null,
  "react_mode": false,
  "max_steps": 5
}
Field Type Required Description
message string User's question in Vietnamese
user_id string User ID for session (default: "anonymous")
session_id string Session ID (default: "default")
provider string "Google" or "MegaLLM" (default: "MegaLLM")
model string LLM model name
image_url string Base64 image for visual search
react_mode boolean Enable multi-step reasoning (default: false)
max_steps integer Max reasoning steps 1-10 (default: 5)

Response:

{
  "response": "Mình gợi ý 3 quán cafe rất đẹp gần Mỹ Khê...",
  "status": "success",
  "provider": "MegaLLM",
  "model": "deepseek-ai/deepseek-v3.1-terminus",
  "user_id": "user_123",
  "session_id": "default",
  "places": [
    {
      "place_id": "cafe_001",
      "name": "Cabanon Palace",
      "category": "restaurant",
      "lat": 16.06,
      "lng": 108.24,
      "rating": 4.8,
      "address": "123 Võ Nguyên Giáp"
    },
    {
      "place_id": "cafe_002",
      "name": "Be Man Restaurant",
      "category": "restaurant",
      "lat": 16.07,
      "lng": 108.25,
      "rating": 4.5,
      "address": "456 Phạm Văn Đồng"
    }
  ],
  "tools_used": ["find_nearby_places"],
  "duration_ms": 5748.23
}

Note: places array contains LLM-selected places with full details. FE can render these as cards separately from text response.


POST /chat/clear

Clear conversation history.

Request:

{
  "user_id": "user_123",
  "session_id": "default"
}

Response:

{
  "status": "success",
  "message": "Cleared session 'default' for user_123"
}

GET /chat/history/{user_id}

Get chat session metadata (list of sessions, counts).

Response:

{
  "user_id": "user_123",
  "sessions": ["default", "trip_planning"],
  "current_session": "default",
  "message_count": 12
}

GET /chat/messages/{user_id}

Get actual chat messages from a session.

Query Params: ?session_id=default

Response:

{
  "user_id": "user_123",
  "session_id": "default",
  "messages": [
    {
      "role": "user",
      "content": "Tìm quán cafe gần Mỹ Khê",
      "timestamp": "2025-01-01T10:00:00"
    },
    {
      "role": "assistant",
      "content": "Dựa trên yêu cầu của bạn...",
      "timestamp": "2025-01-01T10:00:05"
    }
  ],
  "count": 2
}

POST /image-search

Search places by uploaded image.

Request: multipart/form-data

  • image: File (required)
  • limit: integer (default: 10)

Response:

{
  "results": [
    {
      "place_id": "cafe_123",
      "name": "Nhớ Một Người",
      "category": "Cafe",
      "rating": 4.9,
      "similarity": 0.85,
      "image_url": "https://..."
    }
  ],
  "total": 5
}

Upload API

Base path: /upload

POST /upload/image

Upload image to Supabase Storage and get public URL.

Use this to get an image URL for the /chat endpoint's image_url parameter.

Request: multipart/form-data

  • file: Image file (required)
  • user_id: string (optional, for organizing uploads)

Supported formats: JPEG, PNG, WebP, GIF
Max size: 10MB

Response:

{
  "url": "https://xxx.supabase.co/storage/v1/object/public/image/user123/20250101_120000_abc123.jpg",
  "path": "user123/20250101_120000_abc123.jpg",
  "size": 245678,
  "content_type": "image/jpeg"
}

Usage Flow:

1. POST /upload/image → get URL
2. POST /chat { image_url: URL } → visual search

User Profile API

Base path: /users

GET /users/me

Get current user's profile.

Query: ?user_id=uuid-here

Response:

{
  "profile": {
    "id": "uuid-here",
    "full_name": "Nguyen Van A",
    "phone": "0901234567",
    "role": "tourist",
    "locale": "vi_VN",
    "avatar_url": "https://...",
    "created_at": "2025-01-01T00:00:00Z",
    "updated_at": "2025-01-01T00:00:00Z"
  },
  "message": "Profile retrieved"
}

PUT /users/me

Update current user's profile.

Query: ?user_id=uuid-here

Request:

{
  "full_name": "Nguyen Van B",
  "phone": "0909876543",
  "locale": "en_US",
  "avatar_url": "https://..."
}

GET /users/{user_id}

Get user profile by ID (admin only).


Itineraries API

Base path: /itineraries

Multi-day trip planning with persistent storage (Supabase)

POST /itineraries

Create new itinerary.

Query: ?user_id=uuid-here

Request:

{
  "title": "Da Nang 3 Days Trip",
  "start_date": "2025-02-01",
  "end_date": "2025-02-03",
  "total_days": 3,
  "total_budget": 5000000,
  "currency": "VND"
}

Response:

{
  "itinerary": {
    "id": "itinerary-uuid",
    "user_id": "user-uuid",
    "title": "Da Nang 3 Days Trip",
    "start_date": "2025-02-01",
    "end_date": "2025-02-03",
    "total_days": 3,
    "total_budget": 5000000,
    "currency": "VND",
    "stops": [],
    "created_at": "...",
    "updated_at": "..."
  },
  "message": "Itinerary created"
}

GET /itineraries

List user's itineraries.

Query: ?user_id=uuid-here

Response:

[
  {
    "id": "itinerary-uuid",
    "title": "Da Nang 3 Days Trip",
    "start_date": "2025-02-01",
    "end_date": "2025-02-03",
    "total_days": 3,
    "stop_count": 8,
    "created_at": "..."
  }
]

GET /itineraries/{itinerary_id}

Get itinerary with all stops.

Query: ?user_id=uuid-here


PUT /itineraries/{itinerary_id}

Update itinerary details.

Request:

{
  "title": "Updated Title",
  "total_budget": 6000000
}

DELETE /itineraries/{itinerary_id}

Delete itinerary and all stops.


POST /itineraries/{itinerary_id}/stops

Add stop to itinerary.

Request:

{
  "place_id": "cafe_123",
  "day_index": 1,
  "order_index": 1,
  "arrival_time": "2025-02-01T09:00:00Z",
  "stay_minutes": 60,
  "notes": "Morning coffee",
  "tags": ["cafe", "breakfast"]
}

PUT /itineraries/{itinerary_id}/stops/{stop_id}

Update stop.


DELETE /itineraries/{itinerary_id}/stops/{stop_id}

Remove stop.


Trip Planner API

Base path: /planner

POST /planner/create

Create a new trip plan.

Query: ?user_id=user_123

Request:

{
  "name": "My Da Nang Trip"
}

Response:

{
  "plan_id": "plan_abc123",
  "name": "My Da Nang Trip",
  "message": "Created plan 'My Da Nang Trip'"
}

GET /planner/{plan_id}

Get a plan by ID.

Query: ?user_id=user_123

Response:

{
  "plan": {
    "plan_id": "plan_abc123",
    "name": "My Da Nang Trip",
    "items": [
      {
        "item_id": "item_1",
        "order": 0,
        "name": "FIRGUN CORNER COFFEE",
        "category": "Cafe",
        "lat": 16.06,
        "lng": 108.22,
        "rating": 4.5,
        "distance_from_prev_km": null
      }
    ],
    "total_distance_km": 0,
    "estimated_duration_min": 0
  },
  "message": "Plan retrieved"
}

POST /planner/{plan_id}/add

Add a place to the plan.

Query: ?user_id=user_123

Request:

{
  "place": {
    "place_id": "cafe_123",
    "name": "FIRGUN CORNER COFFEE",
    "category": "Cafe",
    "lat": 16.06,
    "lng": 108.22,
    "rating": 4.5
  },
  "notes": "Morning coffee"
}

Response: PlanItem object


DELETE /planner/{plan_id}/remove/{item_id}

Remove a place from the plan.

Query: ?user_id=user_123

Response:

{
  "status": "success",
  "message": "Removed item item_1"
}

PUT /planner/{plan_id}/reorder

Reorder places manually.

Query: ?user_id=user_123

Request:

{
  "new_order": ["item_3", "item_1", "item_2"]
}

POST /planner/{plan_id}/optimize

Optimize route using TSP algorithm.

Query: ?user_id=user_123&start_index=0

Response:

{
  "plan_id": "plan_abc123",
  "items": [...],
  "total_distance_km": 12.5,
  "estimated_duration_min": 45,
  "distance_saved_km": 3.2,
  "message": "Route optimized! Total: 12.5km, ~45min"
}

DELETE /planner/{plan_id}

Delete a plan.

Query: ?user_id=user_123


POST /planner/{plan_id}/get-plan

Generate an optimized Smart Plan with social media research and optimal timing.

Query: ?user_id=user_123

Request:

{
  "include_social_research": true,
  "freshness": "pw"
}
Field Type Description
include_social_research boolean Enable Brave Search for reviews (default: true)
freshness string "pw" = past week, "pm" = past month

Response:

{
  "plan": {
    "itinerary_id": "plan_abc123",
    "title": "Da Nang Test Trip",
    "total_days": 1,
    "days": [
      {
        "day_index": 1,
        "date": null,
        "places": [
          {
            "place_id": "my_khe_1",
            "name": "Bãi biển Mỹ Khê",
            "category": "beach",
            "lat": 16.0544,
            "lng": 108.245,
            "recommended_time": "05:30",
            "suggested_duration_min": 90,
            "tips": [
              "Đón bình minh đẹp nhất vào khoảng 5h30 - 6h00 sáng.",
              "Xem ngư dân kéo lưới và mua hải sản tươi sống."
            ],
            "highlights": "Summary from social research...",
            "social_mentions": ["[TikTok] Review Mỹ Khê..."],
            "order": 1
          },
          {
            "place_id": "cau_rong_1",
            "name": "Cầu Rồng",
            "category": "attraction",
            "recommended_time": "20:30",
            "suggested_duration_min": 60,
            "tips": [
              "Nếu đi vào Thứ 7 hoặc Chủ Nhật, Rồng sẽ phun lửa và nước vào lúc 21:00.",
              "Đứng ở phía đầu Rồng để xem rõ nhất."
            ],
            "order": 2
          }
        ],
        "day_summary": "Ngày 1: 2 địa điểm",
        "day_distance_km": 3.57
      }
    ],
    "summary": "Lịch trình với 2 địa điểm trong 1 ngày.",
    "total_distance_km": 3.57,
    "estimated_total_duration_min": 150,
    "generated_at": "2025-12-20T06:20:59"
  },
  "research_count": 5,
  "generation_time_ms": 9486.47,
  "message": "Smart plan generated with 5 social mentions"
}

Features:

  • Optimal Timing: Da Nang local knowledge (Dragon Bridge 21h, Mỹ Khê sunrise)
  • Social Research: Pulls reviews from TikTok, Facebook, Reddit via Brave API
  • LLM Enhancement: Uses Gemini 3 Flash for tips and scheduling
  • Distance Calculation: Haversine formula for route distances

POST /itineraries/{itinerary_id}/get-plan

Same as above, but for multi-day itineraries (persistent storage).

Query: ?user_id=uuid-here

Request/Response: Same format as planner get-plan


Utility Endpoints

GET /health

Health check. Returns {"status": "ok"}

POST /nearby

Find nearby places (direct Neo4j query).

Request:

{
  "lat": 16.0626442,
  "lng": 108.2462143,
  "max_distance_km": 3.0,
  "category": "cafe",
  "limit": 10
}

Models

Place Object

interface Place {
  place_id: string;
  name: string;
  category?: string;
  lat?: number;
  lng?: number;
  rating?: number;
  description?: string;
}

PlanItem

interface PlanItem {
  item_id: string;
  order: number;
  name: string;
  category?: string;
  lat: number;
  lng: number;
  rating?: number;
  notes?: string;
  distance_from_prev_km?: number;
}

WorkflowStep

interface WorkflowStep {
  step: string;
  tool?: string;
  purpose: string;
  results: number;
}

SmartPlan (Get Plan Response)

interface SmartPlan {
  itinerary_id: string;
  title: string;
  total_days: number;
  days: DayPlan[];
  summary: string;
  total_distance_km: number;
  estimated_total_duration_min: number;
  generated_at: string;
}

interface DayPlan {
  day_index: number;
  date?: string;
  places: PlaceDetail[];
  day_summary: string;
  day_distance_km: number;
}

interface PlaceDetail {
  place_id: string;
  name: string;
  category: string;
  lat: number;
  lng: number;
  recommended_time: string;     // "05:30", "21:00"
  suggested_duration_min: number;
  tips: string[];               // ["Xem cầu rồng phun lửa..."]
  highlights: string;           // Summary from social research
  social_mentions: string[];    // ["[TikTok] Review..."]
  order: number;
}

Usage Examples

JavaScript/Fetch

// Chat
const response = await fetch('https://huggingface.co/proxy/cuong2004-localmate.hf.space/api/v1/chat', {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({
    message: 'Quán cafe view đẹp gần Mỹ Khê',
    user_id: 'my_user',
    react_mode: false
  })
});
const data = await response.json();
console.log(data.response);

cURL

curl -X POST "https://huggingface.co/proxy/cuong2004-localmate.hf.space/api/v1/chat" \
  -H "Content-Type: application/json" \
  -d '{"message": "Nhà hàng hải sản ngon", "user_id": "test"}'

Error Responses

Status Description
400 Bad Request - Invalid parameters
404 Not Found - Resource doesn't exist
422 Validation Error - Check request body
500 Server Error - Check logs
{
  "detail": "Plan not found"
}