|
@@ -0,0 +1,84 @@
|
|
|
+import asyncio
|
|
|
+import copy
|
|
|
+import json
|
|
|
+import re
|
|
|
+from urllib import parse
|
|
|
+
|
|
|
+import requests
|
|
|
+from shapely import Polygon, wkt
|
|
|
+
|
|
|
+from qwen_agent.messages.context_message import ChatResponseChoice, ChatResponseStreamChoice
|
|
|
+from qwen_agent.sub_agent.BaseSubAgent import BaseSubAgent
|
|
|
+from qwen_agent.tools.gis.geocoder.geocoder_tdt import GeocoderTDT
|
|
|
+from qwen_agent.utils.gis_util import get_area
|
|
|
+from qwen_agent.utils.util import extract_json
|
|
|
+
|
|
|
+
|
|
|
+class GisLayerOperationAgent(BaseSubAgent):
|
|
|
+ def __init__(self, llm=None, llm_name=None, stream=False, name='gis_geocoder_agent'):
|
|
|
+ super(GisLayerOperationAgent, self).__init__(llm, llm_name, stream, name=name)
|
|
|
+ self.tool_list = []
|
|
|
+ self.REACT_INSTRUCTION = ""
|
|
|
+ self.SubAgent_PROMPT = """你是一个GIS图层控制系统,需要将自然语言指令解析为结构化操作。请严格按以下规则处理:
|
|
|
+ <处理规则>
|
|
|
+ 1. 只关注图层开关指令,忽略无关内容
|
|
|
+ 2. 支持的同义动词:
|
|
|
+ - 打开:开启/显示/激活
|
|
|
+ - 关闭:隐藏/禁用/取消
|
|
|
+ 3. 图层名称可能是字母、数字或中文组合(如"道路层"/"Layer1")
|
|
|
+ 4. 多个操作按指令顺序保持
|
|
|
+ 5. 未提及的图层保持原状
|
|
|
+ 6. 生成的操作命令结果中,layer图层名称字段中不包含'图层'后缀
|
|
|
+ </处理规则>
|
|
|
+
|
|
|
+ <输出格式>
|
|
|
+ 必须返回如下JSON结构:
|
|
|
+ {{
|
|
|
+ "operations": [
|
|
|
+ {{"action": "open/close", "layer": "图层名称"}},
|
|
|
+ ...
|
|
|
+ ]
|
|
|
+ }}
|
|
|
+ </输出格式>
|
|
|
+ <示例>
|
|
|
+ 用户问:请把永久基本农田图层和道路层显示出来,关掉旧版标注
|
|
|
+ 回应:
|
|
|
+ {{
|
|
|
+ "operations": [
|
|
|
+ {{"action": "open", "layer": "永久基本农田"}},
|
|
|
+ {{"action": "open", "layer": "道路层"}},
|
|
|
+ {{"action": "close", "layer": "旧版标注"}}
|
|
|
+ ]
|
|
|
+ }}
|
|
|
+ </示例>
|
|
|
+ 请严格按上述要求生成JSON响应,不要包含任何额外内容:
|
|
|
+ """
|
|
|
+
|
|
|
+ async def run(self, plan_context, messages=[]):
|
|
|
+ query = plan_context.user_request
|
|
|
+ _messages = copy.deepcopy(messages)
|
|
|
+ _messages.insert(0, {'role': 'system', 'content': self.SubAgent_PROMPT})
|
|
|
+ _messages.append({'role': 'user', 'content': query})
|
|
|
+ for msg in _messages:
|
|
|
+ if 'history' not in msg:
|
|
|
+ yield ChatResponseChoice(
|
|
|
+ role=msg['role'],
|
|
|
+ content=msg['content']
|
|
|
+ )
|
|
|
+ rsp = await self.llm.chat(model=self.llm_name, messages=_messages, stream=self.stream)
|
|
|
+
|
|
|
+ await asyncio.sleep(0.2)
|
|
|
+ if self.stream:
|
|
|
+ res = ""
|
|
|
+ async for chunk in rsp:
|
|
|
+ res += chunk
|
|
|
+ yield ChatResponseStreamChoice(role='assistant', delta=chunk)
|
|
|
+ yield ChatResponseStreamChoice(role='assistant', finish_reason='stop')
|
|
|
+ else:
|
|
|
+ res = rsp
|
|
|
+ yield ChatResponseChoice(role='assistant', content=rsp)
|
|
|
+
|
|
|
+ self.exec_res = f"\n```json\n{res}\n```\n"
|
|
|
+
|
|
|
+
|
|
|
+
|