geoai-py 0.18.2__tar.gz → 0.19.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {geoai_py-0.18.2 → geoai_py-0.19.0}/.gitignore +1 -0
- {geoai_py-0.18.2 → geoai_py-0.19.0}/.pre-commit-config.yaml +2 -2
- {geoai_py-0.18.2 → geoai_py-0.19.0}/PKG-INFO +3 -1
- {geoai_py-0.18.2 → geoai_py-0.19.0}/geoai/__init__.py +23 -1
- {geoai_py-0.18.2 → geoai_py-0.19.0}/geoai/agents/__init__.py +1 -0
- {geoai_py-0.18.2 → geoai_py-0.19.0}/geoai/agents/geo_agents.py +74 -29
- {geoai_py-0.18.2 → geoai_py-0.19.0}/geoai/geoai.py +2 -0
- geoai_py-0.19.0/geoai/landcover_train.py +685 -0
- geoai_py-0.19.0/geoai/landcover_utils.py +383 -0
- geoai_py-0.19.0/geoai/map_widgets.py +730 -0
- geoai_py-0.19.0/geoai/moondream.py +990 -0
- {geoai_py-0.18.2 → geoai_py-0.19.0}/geoai/tools/__init__.py +11 -0
- geoai_py-0.19.0/geoai/tools/sr.py +194 -0
- {geoai_py-0.18.2 → geoai_py-0.19.0}/geoai/utils.py +329 -1881
- {geoai_py-0.18.2 → geoai_py-0.19.0}/geoai_py.egg-info/PKG-INFO +3 -1
- {geoai_py-0.18.2 → geoai_py-0.19.0}/geoai_py.egg-info/SOURCES.txt +4 -0
- {geoai_py-0.18.2 → geoai_py-0.19.0}/geoai_py.egg-info/requires.txt +3 -0
- {geoai_py-0.18.2 → geoai_py-0.19.0}/mkdocs.yml +4 -0
- {geoai_py-0.18.2 → geoai_py-0.19.0}/pyproject.toml +3 -2
- geoai_py-0.18.2/geoai/map_widgets.py +0 -174
- {geoai_py-0.18.2 → geoai_py-0.19.0}/.dockerignore +0 -0
- {geoai_py-0.18.2 → geoai_py-0.19.0}/.editorconfig +0 -0
- {geoai_py-0.18.2 → geoai_py-0.19.0}/CITATION.cff +0 -0
- {geoai_py-0.18.2 → geoai_py-0.19.0}/Dockerfile +0 -0
- {geoai_py-0.18.2 → geoai_py-0.19.0}/LICENSE +0 -0
- {geoai_py-0.18.2 → geoai_py-0.19.0}/MANIFEST.in +0 -0
- {geoai_py-0.18.2 → geoai_py-0.19.0}/README.md +0 -0
- {geoai_py-0.18.2 → geoai_py-0.19.0}/geoai/agents/catalog_models.py +0 -0
- {geoai_py-0.18.2 → geoai_py-0.19.0}/geoai/agents/catalog_tools.py +0 -0
- {geoai_py-0.18.2 → geoai_py-0.19.0}/geoai/agents/map_tools.py +0 -0
- {geoai_py-0.18.2 → geoai_py-0.19.0}/geoai/agents/stac_models.py +0 -0
- {geoai_py-0.18.2 → geoai_py-0.19.0}/geoai/agents/stac_tools.py +0 -0
- {geoai_py-0.18.2 → geoai_py-0.19.0}/geoai/change_detection.py +0 -0
- {geoai_py-0.18.2 → geoai_py-0.19.0}/geoai/classify.py +0 -0
- {geoai_py-0.18.2 → geoai_py-0.19.0}/geoai/detectron2.py +0 -0
- {geoai_py-0.18.2 → geoai_py-0.19.0}/geoai/dinov3.py +0 -0
- {geoai_py-0.18.2 → geoai_py-0.19.0}/geoai/download.py +0 -0
- {geoai_py-0.18.2 → geoai_py-0.19.0}/geoai/extract.py +0 -0
- {geoai_py-0.18.2 → geoai_py-0.19.0}/geoai/hf.py +0 -0
- {geoai_py-0.18.2 → geoai_py-0.19.0}/geoai/sam.py +0 -0
- {geoai_py-0.18.2 → geoai_py-0.19.0}/geoai/segment.py +0 -0
- {geoai_py-0.18.2 → geoai_py-0.19.0}/geoai/segmentation.py +0 -0
- {geoai_py-0.18.2 → geoai_py-0.19.0}/geoai/timm_segment.py +0 -0
- {geoai_py-0.18.2 → geoai_py-0.19.0}/geoai/timm_train.py +0 -0
- {geoai_py-0.18.2 → geoai_py-0.19.0}/geoai/tools/cloudmask.py +0 -0
- {geoai_py-0.18.2 → geoai_py-0.19.0}/geoai/tools/multiclean.py +0 -0
- {geoai_py-0.18.2 → geoai_py-0.19.0}/geoai/train.py +0 -0
- {geoai_py-0.18.2 → geoai_py-0.19.0}/geoai_py.egg-info/dependency_links.txt +0 -0
- {geoai_py-0.18.2 → geoai_py-0.19.0}/geoai_py.egg-info/entry_points.txt +0 -0
- {geoai_py-0.18.2 → geoai_py-0.19.0}/geoai_py.egg-info/top_level.txt +0 -0
- {geoai_py-0.18.2 → geoai_py-0.19.0}/pytest.ini +0 -0
- {geoai_py-0.18.2 → geoai_py-0.19.0}/requirements.txt +0 -0
- {geoai_py-0.18.2 → geoai_py-0.19.0}/requirements_docs.txt +0 -0
- {geoai_py-0.18.2 → geoai_py-0.19.0}/setup.cfg +0 -0
- {geoai_py-0.18.2 → geoai_py-0.19.0}/tests/__init__.py +0 -0
- {geoai_py-0.18.2 → geoai_py-0.19.0}/tests/create_test_data.py +0 -0
- {geoai_py-0.18.2 → geoai_py-0.19.0}/tests/test_classify.py +0 -0
- {geoai_py-0.18.2 → geoai_py-0.19.0}/tests/test_download.py +0 -0
- {geoai_py-0.18.2 → geoai_py-0.19.0}/tests/test_extract.py +0 -0
- {geoai_py-0.18.2 → geoai_py-0.19.0}/tests/test_fixtures.py +0 -0
- {geoai_py-0.18.2 → geoai_py-0.19.0}/tests/test_geoai.py +0 -0
- {geoai_py-0.18.2 → geoai_py-0.19.0}/tests/test_segment.py +0 -0
- {geoai_py-0.18.2 → geoai_py-0.19.0}/tests/test_utils.py +0 -0
|
@@ -12,7 +12,7 @@ repos:
|
|
|
12
12
|
args: ["--maxkb=500"]
|
|
13
13
|
|
|
14
14
|
- repo: https://github.com/psf/black-pre-commit-mirror
|
|
15
|
-
rev: 25.
|
|
15
|
+
rev: 25.12.0
|
|
16
16
|
hooks:
|
|
17
17
|
- id: black-jupyter
|
|
18
18
|
|
|
@@ -27,6 +27,6 @@ repos:
|
|
|
27
27
|
]
|
|
28
28
|
|
|
29
29
|
- repo: https://github.com/kynan/nbstripout
|
|
30
|
-
rev: 0.8.
|
|
30
|
+
rev: 0.8.2
|
|
31
31
|
hooks:
|
|
32
32
|
- id: nbstripout
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: geoai-py
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.19.0
|
|
4
4
|
Summary: A Python package for using Artificial Intelligence (AI) with geospatial data
|
|
5
5
|
Author-email: Qiusheng Wu <giswqs@gmail.com>
|
|
6
6
|
License: MIT License
|
|
@@ -57,6 +57,8 @@ Requires-Dist: strands-agents-tools; extra == "agents"
|
|
|
57
57
|
Requires-Dist: strands-agents[ollama]; extra == "agents"
|
|
58
58
|
Requires-Dist: strands-agents[anthropic]; extra == "agents"
|
|
59
59
|
Requires-Dist: strands-agents[openai]; extra == "agents"
|
|
60
|
+
Provides-Extra: sr
|
|
61
|
+
Requires-Dist: opensr-model; extra == "sr"
|
|
60
62
|
Dynamic: license-file
|
|
61
63
|
|
|
62
64
|
# GeoAI: Artificial Intelligence for Geospatial Data
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
__author__ = """Qiusheng Wu"""
|
|
4
4
|
__email__ = "giswqs@gmail.com"
|
|
5
|
-
__version__ = "0.
|
|
5
|
+
__version__ = "0.19.0"
|
|
6
6
|
|
|
7
7
|
|
|
8
8
|
import os
|
|
@@ -136,3 +136,25 @@ try:
|
|
|
136
136
|
except ImportError:
|
|
137
137
|
# MultiClean not available (missing dependency)
|
|
138
138
|
pass
|
|
139
|
+
|
|
140
|
+
# Removed redundant cloud mask imports; these are already available via the tools subpackage.
|
|
141
|
+
|
|
142
|
+
try:
|
|
143
|
+
from .tools import super_resolution
|
|
144
|
+
except ImportError:
|
|
145
|
+
# super_resolution not available (missing dependency)
|
|
146
|
+
pass
|
|
147
|
+
|
|
148
|
+
# Moondream Vision Language Model
|
|
149
|
+
try:
|
|
150
|
+
from .moondream import (
|
|
151
|
+
MoondreamGeo,
|
|
152
|
+
moondream_caption,
|
|
153
|
+
moondream_query,
|
|
154
|
+
moondream_detect,
|
|
155
|
+
moondream_point,
|
|
156
|
+
)
|
|
157
|
+
from .map_widgets import moondream_gui
|
|
158
|
+
except ImportError:
|
|
159
|
+
# Moondream not available (missing dependency)
|
|
160
|
+
pass
|
|
@@ -17,6 +17,7 @@ from strands.models import BedrockModel
|
|
|
17
17
|
from strands.models.anthropic import AnthropicModel
|
|
18
18
|
from strands.models.ollama import OllamaModel as _OllamaModel
|
|
19
19
|
from strands.models.openai import OpenAIModel
|
|
20
|
+
from strands.models.gemini import GeminiModel
|
|
20
21
|
|
|
21
22
|
from .catalog_tools import CatalogTools
|
|
22
23
|
from .map_tools import MapSession, MapTools
|
|
@@ -202,6 +203,40 @@ def create_bedrock_model(
|
|
|
202
203
|
)
|
|
203
204
|
|
|
204
205
|
|
|
206
|
+
def create_gemini_model(
|
|
207
|
+
model_id: str = "gemini-2.5-flash",
|
|
208
|
+
api_key: str = None,
|
|
209
|
+
client_args: dict = None,
|
|
210
|
+
**kwargs: Any,
|
|
211
|
+
) -> GeminiModel:
|
|
212
|
+
"""Create a Gemini model.
|
|
213
|
+
|
|
214
|
+
Args:
|
|
215
|
+
model_id: Gemini model ID.
|
|
216
|
+
api_key: Gemini API key.
|
|
217
|
+
client_args: Client arguments for the Gemini model.
|
|
218
|
+
**kwargs: Additional keyword arguments for the Gemini model.
|
|
219
|
+
|
|
220
|
+
Returns:
|
|
221
|
+
GeminiModel: A Gemini model.
|
|
222
|
+
"""
|
|
223
|
+
|
|
224
|
+
if api_key is None and (client_args is None or "api_key" not in client_args):
|
|
225
|
+
try:
|
|
226
|
+
api_key = os.getenv("GOOGLE_API_KEY", None)
|
|
227
|
+
if api_key is None:
|
|
228
|
+
raise ValueError("GOOGLE_API_KEY is not set")
|
|
229
|
+
except Exception:
|
|
230
|
+
raise ValueError("GOOGLE_API_KEY is not set")
|
|
231
|
+
|
|
232
|
+
if client_args is None:
|
|
233
|
+
client_args = kwargs.get("client_args", {})
|
|
234
|
+
if "api_key" not in client_args and api_key is not None:
|
|
235
|
+
client_args["api_key"] = api_key
|
|
236
|
+
|
|
237
|
+
return GeminiModel(client_args=client_args, model_id=model_id, **kwargs)
|
|
238
|
+
|
|
239
|
+
|
|
205
240
|
class GeoAgent(Agent):
|
|
206
241
|
"""Geospatial AI agent with interactive mapping capabilities."""
|
|
207
242
|
|
|
@@ -229,15 +264,10 @@ class GeoAgent(Agent):
|
|
|
229
264
|
model_args = {}
|
|
230
265
|
|
|
231
266
|
# --- save a model factory we can call each turn ---
|
|
232
|
-
if model
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
)
|
|
237
|
-
)
|
|
238
|
-
elif isinstance(model, str):
|
|
239
|
-
self._model_factory: Callable[[], BedrockModel] = (
|
|
240
|
-
lambda: create_bedrock_model(model_id=model, **model_args)
|
|
267
|
+
if isinstance(model, str) and (":" in model or model.startswith("llama")):
|
|
268
|
+
# treat ANY "llama..." model id as Ollama
|
|
269
|
+
self._model_factory = lambda m=model: create_ollama_model(
|
|
270
|
+
host="http://localhost:11434", model_id=m, **model_args
|
|
241
271
|
)
|
|
242
272
|
elif isinstance(model, OllamaModel):
|
|
243
273
|
# Extract configuration from existing OllamaModel and create new instances
|
|
@@ -267,6 +297,20 @@ class GeoAgent(Agent):
|
|
|
267
297
|
model_id=mid, client_args=client_args, **model_args
|
|
268
298
|
)
|
|
269
299
|
)
|
|
300
|
+
elif isinstance(model, GeminiModel):
|
|
301
|
+
# Extract configuration from existing GeminiModel and create new instances
|
|
302
|
+
model_id = model.config["model_id"]
|
|
303
|
+
client_args = model.client_args.copy()
|
|
304
|
+
self._model_factory: Callable[[], GeminiModel] = (
|
|
305
|
+
lambda mid=model_id, client_args=client_args: create_gemini_model(
|
|
306
|
+
model_id=mid, client_args=client_args, **model_args
|
|
307
|
+
)
|
|
308
|
+
)
|
|
309
|
+
elif isinstance(model, str):
|
|
310
|
+
# Only Bedrock IDs here, not LLaMA
|
|
311
|
+
self._model_factory = lambda m=model: create_bedrock_model(
|
|
312
|
+
model_id=m, **model_args
|
|
313
|
+
)
|
|
270
314
|
else:
|
|
271
315
|
raise ValueError(f"Invalid model: {model}")
|
|
272
316
|
|
|
@@ -473,7 +517,7 @@ class GeoAgent(Agent):
|
|
|
473
517
|
f"<div style='margin:6px 0;padding:6px 8px;border-radius:8px;background:#f7f7f7;'><b>Agent</b>: {_esc(mm)}</div>"
|
|
474
518
|
)
|
|
475
519
|
self._ui.log.value = (
|
|
476
|
-
"<div>"
|
|
520
|
+
"<div style='height:100%; overflow-y:auto;'>"
|
|
477
521
|
+ (
|
|
478
522
|
"".join(parts)
|
|
479
523
|
if parts
|
|
@@ -643,16 +687,12 @@ class STACAgent(Agent):
|
|
|
643
687
|
model_args = {}
|
|
644
688
|
|
|
645
689
|
# --- save a model factory we can call each turn ---
|
|
646
|
-
if model
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
)
|
|
651
|
-
)
|
|
652
|
-
elif isinstance(model, str):
|
|
653
|
-
self._model_factory: Callable[[], BedrockModel] = (
|
|
654
|
-
lambda: create_bedrock_model(model_id=model, **model_args)
|
|
690
|
+
if isinstance(model, str) and (":" in model or model.startswith("llama")):
|
|
691
|
+
# treat ANY "llama..." model id as Ollama
|
|
692
|
+
self._model_factory = lambda m=model: create_ollama_model(
|
|
693
|
+
host="http://localhost:11434", model_id=m, **model_args
|
|
655
694
|
)
|
|
695
|
+
|
|
656
696
|
elif isinstance(model, OllamaModel):
|
|
657
697
|
# Extract configuration from existing OllamaModel and create new instances
|
|
658
698
|
model_id = model.config["model_id"]
|
|
@@ -681,6 +721,11 @@ class STACAgent(Agent):
|
|
|
681
721
|
model_id=mid, client_args=client_args, **model_args
|
|
682
722
|
)
|
|
683
723
|
)
|
|
724
|
+
elif isinstance(model, str):
|
|
725
|
+
# Only Bedrock IDs here, not LLaMA
|
|
726
|
+
self._model_factory = lambda m=model: create_bedrock_model(
|
|
727
|
+
model_id=m, **model_args
|
|
728
|
+
)
|
|
684
729
|
else:
|
|
685
730
|
raise ValueError(f"Invalid model: {model}")
|
|
686
731
|
|
|
@@ -1092,7 +1137,7 @@ CRITICAL: Return ONLY JSON. NO explanatory text, NO made-up data."""
|
|
|
1092
1137
|
f"<div style='margin:6px 0;padding:6px 8px;border-radius:8px;background:#f7f7f7;'><b>Agent</b>: {_esc(mm)}</div>"
|
|
1093
1138
|
)
|
|
1094
1139
|
self._ui.log.value = (
|
|
1095
|
-
"<div>"
|
|
1140
|
+
"<div style='height:100%; overflow-y:auto;'>"
|
|
1096
1141
|
+ (
|
|
1097
1142
|
"".join(parts)
|
|
1098
1143
|
if parts
|
|
@@ -1284,15 +1329,10 @@ class CatalogAgent(Agent):
|
|
|
1284
1329
|
model_args = {}
|
|
1285
1330
|
|
|
1286
1331
|
# --- save a model factory we can call each turn ---
|
|
1287
|
-
if model
|
|
1288
|
-
|
|
1289
|
-
|
|
1290
|
-
|
|
1291
|
-
)
|
|
1292
|
-
)
|
|
1293
|
-
elif isinstance(model, str):
|
|
1294
|
-
self._model_factory: Callable[[], BedrockModel] = (
|
|
1295
|
-
lambda: create_bedrock_model(model_id=model, **model_args)
|
|
1332
|
+
if isinstance(model, str) and (":" in model or model.startswith("llama")):
|
|
1333
|
+
# treat ANY "llama..." model id as Ollama
|
|
1334
|
+
self._model_factory = lambda m=model: create_ollama_model(
|
|
1335
|
+
host="http://localhost:11434", model_id=m, **model_args
|
|
1296
1336
|
)
|
|
1297
1337
|
elif isinstance(model, OllamaModel):
|
|
1298
1338
|
# Extract configuration from existing OllamaModel and create new instances
|
|
@@ -1322,6 +1362,11 @@ class CatalogAgent(Agent):
|
|
|
1322
1362
|
model_id=mid, client_args=client_args, **model_args
|
|
1323
1363
|
)
|
|
1324
1364
|
)
|
|
1365
|
+
elif isinstance(model, str):
|
|
1366
|
+
# Only Bedrock IDs here, not LLaMA
|
|
1367
|
+
self._model_factory = lambda m=model: create_bedrock_model(
|
|
1368
|
+
model_id=m, **model_args
|
|
1369
|
+
)
|
|
1325
1370
|
else:
|
|
1326
1371
|
raise ValueError(f"Invalid model: {model}")
|
|
1327
1372
|
|