The Problem
Clients need a quick way to infer where a photograph was taken without manually searching metadata or crowdsourcing. Existing tools either require manual prompt engineering or lack a programmable interface, creating friction for automated pipelines that need location context (e.g., content moderation, travel‑photo tagging).
What This Does
GeoIntel is a Python package that wraps Google’s Gemini API to generate a structured geo‑location guess from an image. The core logic lives in geointel/geointel.py (class GeoIntel with method locate) and is exposed through two entry points:
- CLI (
geointel/cli.py::main) – parses arguments, callsGeoIntel.locate, and prints or saves JSON. - Web UI (
geointel/web_server.py::create_app) – serves the HTML template ingeointel_ui_template/.
Supporting modules handle image handling (geointel/image_processor.py), API request construction (geointel/api_client.py), response parsing (geointel/response_parser.py), and logging (geointel/logger.py). Errors are centralized in geointel/exceptions.py.
How It Is Wired
Execution begins in geointel/__main__.py, which simply invokes geointel/cli.py::main (line 191). main builds an argparse parser, validates arguments (validate_output_path), and, for CLI mode, calls locate on a GeoIntel instance.
GeoIntel.locate (in geointel/geointel.py) does the following:
- Image validation – calls
geointel/image_processor.py::is_url,validate_image_format, and_validate_size. - Network request – forwards the image (or URL) to
geointel/api_client.py::generate_content. This builds the request (_build_endpoint_url,_build_request_payload,_get_request_headers), sends it viarequests.post, and extracts the raw text with_extract_response_text. - Response handling – passes the raw Gemini reply to
geointel/response_parser.py::parse_response, which cleans JSON (clean_json_string), validates fields (validate_location), and normalizes confidence (normalize_confidence). Errors may be raised asAPIError,ResponseParsingError, orInvalidImageError. - Result formatting –
geointel/cli.py::display_resultsrenders a colored confidence bar (get_confidence_color) and optionally writes JSON (save_results).
The only outbound side‑effects are the POST request to Gemini (via generate_content) and optional file write for --output. No database or persistent storage is used.
The import graph shows geointel/geointel.py as the most connected module (imports 6 others, instability 0.67). geointel/exceptions.py is a leaf with high fan‑in (imported by 7 modules), making it a stable error‑definition hub. The call graph highlights InvalidImageError and GeoIntel as hot spots (called from 4 and 3 places respectively), indicating where a change would have the widest blast radius.
How To Use It
# Install the package
pip install geointel
# Set the Gemini API key (required)
export GEMINI_API_KEY=your_key_here
CLI – Analyze a local file or URL:
geointel --image path/to/photo.jpg # basic
geointel --image path/to/photo.jpg --output result.json
geointel --image https://example.com/img.png --context "Beach sunset" --guess "Malibu"
Web UI – Launch a local server:
geointel --web # default host 127.0.0.1:5000
geointel --web --host 0.0.0.0 --port 4000
Open the printed URL in a browser, upload an image, and view the interactive map.
Real‑World Use
A media‑monitoring service can call GeoIntel.locate(image_path="frame.jpg") inside its ingestion pipeline, store the returned locations array in a search index, and surface geo‑tags alongside article metadata. The SDK example in the README demonstrates this pattern.
Code Health & Issues
- HIGH – No test suite – 14 source files, zero test files. No automated regression safety.
- HIGH – No CI pipeline – No
.github/workflowsor other CI config; changes are not automatically built or tested. - MEDIUM – No dependency update bot – Only
requirements.txtpresent; no Dependabot or Renovate configuration to keep libraries current. - MEDIUM – Deep nesting –
api_client.py,response_parser.py,web_server.pyhave maximum indentation depth 8, making control flow hard to follow. Refactor with early returns or helper functions. - MEDIUM – Broad exception handling –
api_client.pyandresponse_parser.pycatch genericexcept:clauses, swallowing errors. Replace with specific exception types and proper logging.
Other hygiene notes: license file present, no lockfile, no Dockerfile, no committed secrets.
The Bottom Line
GeoIntel delivers a functional, easy‑to‑install CLI and web UI for AI‑based image geo‑location, with clear separation of concerns across modules. However, the lack of tests, CI, and precise error handling poses a risk for production adoption. It is suitable for prototyping or internal tools, but teams should invest in test coverage and CI before relying on it in critical workflows.