Quellcode durchsuchen

feat: Nominatim OpenStreetMap search tool (#5789)

Charles Zhou vor 9 Monaten
Ursprung
Commit
850c2273ee

+ 1 - 0
api/core/tools/provider/_position.yaml

@@ -7,6 +7,7 @@
 - azuredalle
 - stability
 - wikipedia
+- nominatim
 - yahoo
 - arxiv
 - pubmed

Datei-Diff unterdrückt, da er zu groß ist
+ 160 - 0
api/core/tools/provider/builtin/nominatim/_assets/icon.svg


+ 23 - 0
api/core/tools/provider/builtin/nominatim/nominatim.py

@@ -0,0 +1,23 @@
+from typing import Any
+
+from core.tools.errors import ToolProviderCredentialValidationError
+from core.tools.provider.builtin.nominatim.tools.nominatim_search import NominatimSearchTool
+from core.tools.provider.builtin_tool_provider import BuiltinToolProviderController
+
+
+class NominatimProvider(BuiltinToolProviderController):
+    def _validate_credentials(self, credentials: dict[str, Any]) -> None:
+        try:
+            result = NominatimSearchTool().fork_tool_runtime(
+                runtime={
+                    "credentials": credentials,
+                }
+            ).invoke(
+                user_id='',
+                tool_parameters={
+                    'query': 'London',
+                    'limit': 1,
+                },
+            )
+        except Exception as e:
+            raise ToolProviderCredentialValidationError(str(e))

+ 43 - 0
api/core/tools/provider/builtin/nominatim/nominatim.yaml

@@ -0,0 +1,43 @@
+identity:
+  author: Charles Zhou
+  name: nominatim
+  label:
+    en_US: Nominatim
+    zh_Hans: Nominatim
+    de_DE: Nominatim
+    ja_JP: Nominatim
+  description:
+    en_US: Nominatim is a search engine for OpenStreetMap data
+    zh_Hans: Nominatim是OpenStreetMap数据的搜索引擎
+    de_DE: Nominatim ist eine Suchmaschine für OpenStreetMap-Daten
+    ja_JP: NominatimはOpenStreetMapデータの検索エンジンです
+  icon: icon.svg
+  tags:
+    - search
+    - utilities
+credentials_for_provider:
+  base_url:
+    type: text-input
+    required: false
+    default: https://nominatim.openstreetmap.org
+    label:
+      en_US: Nominatim Base URL
+      zh_Hans: Nominatim 基础 URL
+      de_DE: Nominatim Basis-URL
+      ja_JP: Nominatim ベースURL
+    placeholder:
+      en_US: "Enter your Nominatim instance URL (default:
+        https://nominatim.openstreetmap.org)"
+      zh_Hans: 输入您的Nominatim实例URL(默认:https://nominatim.openstreetmap.org)
+      de_DE: "Geben Sie Ihre Nominatim-Instanz-URL ein (Standard:
+        https://nominatim.openstreetmap.org)"
+      ja_JP: NominatimインスタンスのURLを入力してください(デフォルト:https://nominatim.openstreetmap.org)
+    help:
+      en_US: The base URL for the Nominatim instance. Use the default for the public
+        service or enter your self-hosted instance URL.
+      zh_Hans: Nominatim实例的基础URL。使用默认值可访问公共服务,或输入您的自托管实例URL。
+      de_DE: Die Basis-URL für die Nominatim-Instanz. Verwenden Sie den Standardwert
+        für den öffentlichen Dienst oder geben Sie die URL Ihrer selbst
+        gehosteten Instanz ein.
+      ja_JP: NominatimインスタンスのベースURL。公共サービスにはデフォルトを使用するか、自己ホスティングインスタンスのURLを入力してください。
+    url: https://nominatim.org/

+ 47 - 0
api/core/tools/provider/builtin/nominatim/tools/nominatim_lookup.py

@@ -0,0 +1,47 @@
+import json
+from typing import Any, Union
+
+import requests
+
+from core.tools.entities.tool_entities import ToolInvokeMessage
+from core.tools.tool.builtin_tool import BuiltinTool
+
+
+class NominatimLookupTool(BuiltinTool):
+    def _invoke(self, user_id: str, tool_parameters: dict[str, Any]) -> Union[ToolInvokeMessage, list[ToolInvokeMessage]]:
+        osm_ids = tool_parameters.get('osm_ids', '')
+        
+        if not osm_ids:
+            return self.create_text_message('Please provide OSM IDs')
+
+        params = {
+            'osm_ids': osm_ids,
+            'format': 'json',
+            'addressdetails': 1
+        }
+        
+        return self._make_request(user_id, 'lookup', params)
+
+    def _make_request(self, user_id: str, endpoint: str, params: dict) -> ToolInvokeMessage:
+        base_url = self.runtime.credentials.get('base_url', 'https://nominatim.openstreetmap.org')
+        
+        try:
+            headers = {
+                "User-Agent": "DifyNominatimTool/1.0"
+            }
+            s = requests.session()
+            response = s.request(
+                method='GET',
+                headers=headers,
+                url=f"{base_url}/{endpoint}",
+                params=params
+            )
+            response_data = response.json()
+            
+            if response.status_code == 200:
+                s.close()
+                return self.create_text_message(self.summary(user_id=user_id, content=json.dumps(response_data, ensure_ascii=False)))
+            else:
+                return self.create_text_message(f"Error: {response.status_code} - {response.text}")
+        except Exception as e:
+            return self.create_text_message(f"An error occurred: {str(e)}")

+ 31 - 0
api/core/tools/provider/builtin/nominatim/tools/nominatim_lookup.yaml

@@ -0,0 +1,31 @@
+identity:
+  name: nominatim_lookup
+  author: Charles Zhou
+  label:
+    en_US: Nominatim OSM Lookup
+    zh_Hans: Nominatim OSM 对象查找
+    de_DE: Nominatim OSM-Objektsuche
+    ja_JP: Nominatim OSM ルックアップ
+description:
+  human:
+    en_US: Look up OSM objects using their IDs with Nominatim
+    zh_Hans: 使用Nominatim通过ID查找OSM对象
+    de_DE: Suchen Sie OSM-Objekte anhand ihrer IDs mit Nominatim
+    ja_JP: Nominatimを使用してIDでOSMオブジェクトを検索
+  llm: A tool for looking up OpenStreetMap objects using their IDs with Nominatim.
+parameters:
+  - name: osm_ids
+    type: string
+    required: true
+    label:
+      en_US: OSM IDs
+      zh_Hans: OSM ID
+      de_DE: OSM-IDs
+      ja_JP: OSM ID
+    human_description:
+      en_US: Comma-separated list of OSM IDs to lookup (e.g., N123,W456,R789)
+      zh_Hans: 要查找的OSM ID的逗号分隔列表(例如:N123,W456,R789)
+      de_DE: Kommagetrennte Liste von OSM-IDs für die Suche (z.B. N123,W456,R789)
+      ja_JP: 検索するOSM IDのカンマ区切りリスト(例:N123,W456,R789)
+    llm_description: A comma-separated list of OSM IDs (prefixed with N, W, or R) for lookup.
+    form: llm

+ 49 - 0
api/core/tools/provider/builtin/nominatim/tools/nominatim_reverse.py

@@ -0,0 +1,49 @@
+import json
+from typing import Any, Union
+
+import requests
+
+from core.tools.entities.tool_entities import ToolInvokeMessage
+from core.tools.tool.builtin_tool import BuiltinTool
+
+
+class NominatimReverseTool(BuiltinTool):
+    def _invoke(self, user_id: str, tool_parameters: dict[str, Any]) -> Union[ToolInvokeMessage, list[ToolInvokeMessage]]:
+        lat = tool_parameters.get('lat')
+        lon = tool_parameters.get('lon')
+        
+        if lat is None or lon is None:
+            return self.create_text_message('Please provide both latitude and longitude')
+
+        params = {
+            'lat': lat,
+            'lon': lon,
+            'format': 'json',
+            'addressdetails': 1
+        }
+        
+        return self._make_request(user_id, 'reverse', params)
+
+    def _make_request(self, user_id: str, endpoint: str, params: dict) -> ToolInvokeMessage:
+        base_url = self.runtime.credentials.get('base_url', 'https://nominatim.openstreetmap.org')
+        
+        try:
+            headers = {
+                "User-Agent": "DifyNominatimTool/1.0"
+            }
+            s = requests.session()
+            response = s.request(
+                method='GET',
+                headers=headers,
+                url=f"{base_url}/{endpoint}",
+                params=params
+            )
+            response_data = response.json()
+            
+            if response.status_code == 200:
+                s.close()
+                return self.create_text_message(self.summary(user_id=user_id, content=json.dumps(response_data, ensure_ascii=False)))
+            else:
+                return self.create_text_message(f"Error: {response.status_code} - {response.text}")
+        except Exception as e:
+            return self.create_text_message(f"An error occurred: {str(e)}")

+ 47 - 0
api/core/tools/provider/builtin/nominatim/tools/nominatim_reverse.yaml

@@ -0,0 +1,47 @@
+identity:
+  name: nominatim_reverse
+  author: Charles Zhou
+  label:
+    en_US: Nominatim Reverse Geocoding
+    zh_Hans: Nominatim 反向地理编码
+    de_DE: Nominatim Rückwärts-Geocodierung
+    ja_JP: Nominatim リバースジオコーディング
+description:
+  human:
+    en_US: Convert coordinates to addresses using Nominatim
+    zh_Hans: 使用Nominatim将坐标转换为地址
+    de_DE: Konvertieren Sie Koordinaten in Adressen mit Nominatim
+    ja_JP: Nominatimを使用して座標を住所に変換
+  llm: A tool for reverse geocoding using Nominatim, which can convert latitude
+    and longitude coordinates to an address.
+parameters:
+  - name: lat
+    type: number
+    required: true
+    label:
+      en_US: Latitude
+      zh_Hans: 纬度
+      de_DE: Breitengrad
+      ja_JP: 緯度
+    human_description:
+      en_US: Latitude coordinate for reverse geocoding
+      zh_Hans: 用于反向地理编码的纬度坐标
+      de_DE: Breitengrad-Koordinate für die Rückwärts-Geocodierung
+      ja_JP: リバースジオコーディングの緯度座標
+    llm_description: The latitude coordinate for reverse geocoding.
+    form: llm
+  - name: lon
+    type: number
+    required: true
+    label:
+      en_US: Longitude
+      zh_Hans: 经度
+      de_DE: Längengrad
+      ja_JP: 経度
+    human_description:
+      en_US: Longitude coordinate for reverse geocoding
+      zh_Hans: 用于反向地理编码的经度坐标
+      de_DE: Längengrad-Koordinate für die Rückwärts-Geocodierung
+      ja_JP: リバースジオコーディングの経度座標
+    llm_description: The longitude coordinate for reverse geocoding.
+    form: llm

+ 49 - 0
api/core/tools/provider/builtin/nominatim/tools/nominatim_search.py

@@ -0,0 +1,49 @@
+import json
+from typing import Any, Union
+
+import requests
+
+from core.tools.entities.tool_entities import ToolInvokeMessage
+from core.tools.tool.builtin_tool import BuiltinTool
+
+
+class NominatimSearchTool(BuiltinTool):
+    def _invoke(self, user_id: str, tool_parameters: dict[str, Any]) -> Union[ToolInvokeMessage, list[ToolInvokeMessage]]:
+        query = tool_parameters.get('query', '')
+        limit = tool_parameters.get('limit', 10)
+        
+        if not query:
+            return self.create_text_message('Please input a search query')
+
+        params = {
+            'q': query,
+            'format': 'json',
+            'limit': limit,
+            'addressdetails': 1
+        }
+        
+        return self._make_request(user_id, 'search', params)
+
+    def _make_request(self, user_id: str, endpoint: str, params: dict) -> ToolInvokeMessage:
+        base_url = self.runtime.credentials.get('base_url', 'https://nominatim.openstreetmap.org')
+        
+        try:
+            headers = {
+                "User-Agent": "DifyNominatimTool/1.0"
+            }
+            s = requests.session()
+            response = s.request(
+                method='GET',
+                headers=headers,
+                url=f"{base_url}/{endpoint}",
+                params=params
+            )
+            response_data = response.json()
+            
+            if response.status_code == 200:
+                s.close()
+                return self.create_text_message(self.summary(user_id=user_id, content=json.dumps(response_data, ensure_ascii=False)))
+            else:
+                return self.create_text_message(f"Error: {response.status_code} - {response.text}")
+        except Exception as e:
+            return self.create_text_message(f"An error occurred: {str(e)}")

+ 51 - 0
api/core/tools/provider/builtin/nominatim/tools/nominatim_search.yaml

@@ -0,0 +1,51 @@
+identity:
+  name: nominatim_search
+  author: Charles Zhou
+  label:
+    en_US: Nominatim Search
+    zh_Hans: Nominatim 搜索
+    de_DE: Nominatim Suche
+    ja_JP: Nominatim 検索
+description:
+  human:
+    en_US: Search for locations using Nominatim
+    zh_Hans: 使用Nominatim搜索位置
+    de_DE: Suche nach Orten mit Nominatim
+    ja_JP: Nominatimを使用して場所を検索
+  llm: A tool for geocoding using Nominatim, which can search for locations based
+    on addresses or place names.
+parameters:
+  - name: query
+    type: string
+    required: true
+    label:
+      en_US: Search Query
+      zh_Hans: 搜索查询
+      de_DE: Suchanfrage
+      ja_JP: 検索クエリ
+    human_description:
+      en_US: Enter an address or place name to search for
+      zh_Hans: 输入要搜索的地址或地名
+      de_DE: Geben Sie eine Adresse oder einen Ortsnamen für die Suche ein
+      ja_JP: 検索する住所または場所の名前を入力してください
+    llm_description: The search query for Nominatim, which can be an address or place name.
+    form: llm
+  - name: limit
+    type: number
+    default: 10
+    min: 1
+    max: 40
+    required: false
+    label:
+      en_US: Result Limit
+      zh_Hans: 结果限制
+      de_DE: Ergebnislimit
+      ja_JP: 結果の制限
+    human_description:
+      en_US: "Maximum number of results to return (default: 10, max: 40)"
+      zh_Hans: 要返回的最大结果数(默认:10,最大:40)
+      de_DE: "Maximale Anzahl der zurückzugebenden Ergebnisse (Standard: 10, max: 40)"
+      ja_JP: 返す結果の最大数(デフォルト:10、最大:40)
+    llm_description: Limit the number of returned results. The default is 10, and
+      the maximum is 40.
+    form: form

Einige Dateien werden nicht angezeigt, da zu viele Dateien in diesem Diff geändert wurden.