本文介绍下使用dify工作流制作ip归属地查询,并且可视化展示的案例。
工作流类型:workflow
工作流dsl:
app: description: 通过IP地址查询结果,进行html页面的编辑,然后再dify上直接展示html页面内容,而不是带html标签的文本内容 icon: 🤖 icon_background: '#FFEAD5' mode: workflow name: IP地址查询并展示 use_icon_as_answer_icon: false dependencies: - current_identifier: null type: marketplace value: marketplace_plugin_unique_identifier: langgenius/volcengine_maas:0.0.7@f8e44422cfa5b9a6ac1f2d3b43ef1069868efdad1e5cec2590de3f53ceac37b0 kind: app version: 0.1.5 workflow: conversation_variables: [] environment_variables: [] features: file_upload: allowed_file_extensions: - .JPG - .JPEG - .PNG - .GIF - .WEBP - .SVG allowed_file_types: - image allowed_file_upload_methods: - local_file - remote_url enabled: false fileUploadConfig: audio_file_size_limit: 500 batch_count_limit: 50 file_size_limit: 1024 image_file_size_limit: 1000 video_file_size_limit: 10000 workflow_file_upload_limit: 10 image: enabled: false number_limits: 3 transfer_methods: - local_file - remote_url number_limits: 3 opening_statement: '' retriever_resource: enabled: true sensitive_word_avoidance: enabled: false speech_to_text: enabled: false suggested_questions: [] suggested_questions_after_answer: enabled: false text_to_speech: enabled: false language: '' voice: '' graph: edges: - data: isInIteration: false isInLoop: false sourceType: parameter-extractor targetType: if-else id: 1742971637089-source-1742975488354-target source: '1742971637089' sourceHandle: source target: '1742975488354' targetHandle: target type: custom zIndex: 0 - data: isInLoop: false sourceType: if-else targetType: code id: 1742975488354-true-1742971951636-target source: '1742975488354' sourceHandle: 'true' target: '1742971951636' targetHandle: target type: custom zIndex: 0 - data: isInLoop: false sourceType: if-else targetType: template-transform id: 1742975488354-false-1742973316000-target source: '1742975488354' sourceHandle: 'false' target: '1742973316000' targetHandle: target type: custom zIndex: 0 - data: isInIteration: false isInLoop: false sourceType: code targetType: variable-aggregator id: 1742971951636-source-1742975844503-target source: '1742971951636' sourceHandle: source target: '1742975844503' targetHandle: target type: custom zIndex: 0 - data: isInIteration: false isInLoop: false sourceType: variable-aggregator targetType: end id: 1742975844503-source-1742971566530-target source: '1742975844503' sourceHandle: source target: '1742971566530' targetHandle: target type: custom zIndex: 0 - data: isInLoop: false sourceType: template-transform targetType: variable-aggregator id: 1742973316000-source-1742975844503-target source: '1742973316000' sourceHandle: source target: '1742975844503' targetHandle: target type: custom zIndex: 0 - data: isInIteration: false isInLoop: false sourceType: start targetType: if-else id: 1742971513638-source-1742976553035-target source: '1742971513638' sourceHandle: source target: '1742976553035' targetHandle: target type: custom zIndex: 0 - data: isInLoop: false sourceType: if-else targetType: tool id: 1742976553035-true-1742971521243-target source: '1742976553035' sourceHandle: 'true' target: '1742971521243' targetHandle: target type: custom zIndex: 0 - data: isInLoop: false sourceType: if-else targetType: http-request id: 1742976553035-false-1742976403171-target source: '1742976553035' sourceHandle: 'false' target: '1742976403171' targetHandle: target type: custom zIndex: 0 - data: isInIteration: false isInLoop: false sourceType: tool targetType: variable-aggregator id: 1742971521243-source-1742982988677-target source: '1742971521243' sourceHandle: source target: '1742982988677' targetHandle: target type: custom zIndex: 0 - data: isInIteration: false isInLoop: false sourceType: variable-aggregator targetType: parameter-extractor id: 1742982988677-source-1742971637089-target source: '1742982988677' sourceHandle: source target: '1742971637089' targetHandle: target type: custom zIndex: 0 - data: isInLoop: false sourceType: http-request targetType: variable-aggregator id: 1742976403171-source-1742982988677-target source: '1742976403171' sourceHandle: source target: '1742982988677' targetHandle: target type: custom zIndex: 0 nodes: - data: desc: '' selected: false title: 开始 type: start variables: - label: 请输入ipv4地址 max_length: 48 options: [] required: true type: text-input variable: ip - label: 选择查询方式 max_length: 48 options: - 工具 - HTTP请求 required: true type: select variable: type height: 116 id: '1742971513638' position: x: -93 y: 294 positionAbsolute: x: -93 y: 294 selected: false sourcePosition: right targetPosition: left type: custom width: 244 - data: desc: '' is_team_authorization: true output_schema: null paramSchemas: - auto_generate: null default: null form: llm human_description: en_US: The IP address to lookup ja_JP: The IP address to lookup pt_BR: The IP address to lookup zh_Hans: The IP address to lookup label: en_US: ip ja_JP: ip pt_BR: ip zh_Hans: ip llm_description: The IP address to lookup max: null min: null name: ip options: [] placeholder: en_US: The IP address to lookup ja_JP: The IP address to lookup pt_BR: The IP address to lookup zh_Hans: The IP address to lookup precision: null required: true scope: null template: null type: string params: ip: '' provider_id: 4dd48333-2d36-4498-aa66-48cfedafa8b6 provider_name: 查询ip归属地 provider_type: api selected: false title: getIpLocation tool_configurations: {} tool_label: getIpLocation tool_name: getIpLocation tool_parameters: ip: type: mixed value: '{{#1742971513638.ip#}}' type: tool height: 54 id: '1742971521243' position: x: 455 y: 214.851301645003 positionAbsolute: x: 455 y: 214.851301645003 selected: false sourcePosition: right targetPosition: left type: custom width: 244 - data: desc: '' outputs: - value_selector: - '1742975844503' - output variable: result selected: false title: 结束 type: end height: 90 id: '1742971566530' position: x: 2161 y: 363 positionAbsolute: x: 2161 y: 363 selected: true sourcePosition: right targetPosition: left type: custom width: 244 - data: desc: '' instruction: 从{{#1742982988677.output#}}中获取不同属性的值 model: completion_params: temperature: 0.7 mode: chat name: DeepSeek-V3 provider: langgenius/volcengine_maas/volcengine_maas parameters: - description: 获取addr属性的值 name: addr required: false type: string - description: 获取country属性的值 name: country required: false type: string - description: 获取area属性的值 name: area required: false type: string - description: 获取provider属性的值 name: provider required: false type: string query: - '1742982988677' - output reasoning_mode: prompt selected: false title: 参数提取器 type: parameter-extractor variables: [] vision: enabled: false height: 90 id: '1742971637089' position: x: 1028 y: 311 positionAbsolute: x: 1028 y: 311 selected: false sourcePosition: right targetPosition: left type: custom width: 244 - data: code: "def main(addr: str, area: str, country: str, provider: str) -> dict:\n\ \ page_content = f\"\"\"<div style=\"max-width: 800px; margin: 20px auto;\ \ padding: 20px; background-color: white; border-radius: 8px; box-shadow:\ \ 0 2px 10px rgba(0,0,0,0.1);\">\n <h1 style=\"color: #2c3e50; border-bottom:\ \ 2px solid #3498db; padding-bottom: 10px;\">IP查询结果</h1>\n <p>下面展示查询信息</p>\n\ \ <div style=\"background-color: #f9f9f9; border-left: 4px solid\ \ #3498db; padding: 15px; margin: 15px 0; border-radius: 0 4px 4px 0;\"\ >\n <h2>IP: {addr}</h2>\n <p>归属地: {country}{area}</p>\n\ \ <p>运营商: {provider}</p>\n </div>\n </div>\n \"\"\ \"\n return {'result': page_content}" code_language: python3 desc: '' outputs: result: children: null type: string selected: false title: 代码执行 type: code variables: - value_selector: - '1742971637089' - addr variable: addr - value_selector: - '1742971637089' - area variable: area - value_selector: - '1742971637089' - country variable: country - value_selector: - '1742971637089' - provider variable: provider height: 54 id: '1742971951636' position: x: 1591 y: 224.9739670999407 positionAbsolute: x: 1591 y: 224.9739670999407 selected: false sourcePosition: right targetPosition: left type: custom width: 244 - data: desc: '' selected: false template: "<div style=\"max-width: 800px; margin: 20px auto; padding: 20px;\ \ background-color: white; border-radius: 8px; box-shadow: 0 2px 10px rgba(0,0,0,0.1);\"\ >\r\n <h1 style=\"color: #2c3e50; border-bottom: 2px solid #3498db;\ \ padding-bottom: 10px;\">IP查询结果</h1>\r\n <p>下面展示查询信息</p>\r\n \ \ <div style=\"background-color: #f9f9f9; border-left: 4px solid #3498db;\ \ padding: 15px; margin: 15px 0; border-radius: 0 4px 4px 0;\">\r\n \ \ <h2>IP: {{ addr }}</h2>\r\n <p>归属地: {{ country }}{{\ \ area }}</p>\r\n <p>运营商: {{ provider }}</p>\r\n </div>\r\ \n </div>" title: 模板转换 type: template-transform variables: - value_selector: - '1742971637089' - addr variable: addr - value_selector: - '1742971637089' - country variable: country - value_selector: - '1742971637089' - area variable: area - value_selector: - '1742971637089' - provider variable: provider height: 54 id: '1742973316000' position: x: 1591 y: 525.9851444150801 positionAbsolute: x: 1591 y: 525.9851444150801 selected: false sourcePosition: right targetPosition: left type: custom width: 244 - data: cases: - case_id: 'true' conditions: - comparison_operator: is not id: c25b24cf-07d2-4672-88b3-cb63d5d72774 value: 本机地址 varType: string variable_selector: - '1742971637089' - country - comparison_operator: is not id: 36567884-80fe-422b-ad4f-5cb6ed1f70d8 value: 局域网 varType: string variable_selector: - '1742971637089' - country id: 'true' logical_operator: and desc: '' selected: false title: 条件分支(判断位置) type: if-else height: 152 id: '1742975488354' position: x: 1310 y: 311 positionAbsolute: x: 1310 y: 311 selected: false sourcePosition: right targetPosition: left type: custom width: 244 - data: desc: '' output_type: string selected: false title: 显示结果变量聚合器 type: variable-aggregator variables: - - '1742971951636' - result - - '1742973316000' - output height: 130 id: '1742975844503' position: x: 1859 y: 363 positionAbsolute: x: 1859 y: 363 selected: false sourcePosition: right targetPosition: left type: custom width: 244 - data: author: wal desc: '' height: 141 selected: false showAuthor: true text: '{"root":{"children":[{"children":[{"detail":0,"format":0,"mode":"normal","style":"","text":"开始节点添加一个必填参数ip,用于后续节点的一个入参使用","type":"text","version":1}],"direction":"ltr","format":"","indent":0,"type":"paragraph","version":1,"textFormat":0,"textStyle":""},{"children":[{"detail":0,"format":0,"mode":"normal","style":"","text":"为查询ip多途径,这里加一个type参数,用于条件分支节点判断","type":"text","version":1}],"direction":"ltr","format":"","indent":0,"type":"paragraph","version":1,"textFormat":0,"textStyle":""}],"direction":"ltr","format":"","indent":0,"type":"root","version":1}}' theme: blue title: '' type: '' width: 240 height: 141 id: '1742976152791' position: x: -93 y: 627.5 positionAbsolute: x: -93 y: 627.5 selected: false sourcePosition: right targetPosition: left type: custom-note width: 240 - data: author: wal desc: '' height: 119 selected: false showAuthor: true text: '{"root":{"children":[{"children":[{"detail":0,"format":0,"mode":"normal","style":"","text":"此处是自定义的一个工具,由群友@daniel提供的一个查询ip的工具,此处也可以更换为http请求节点,为了演示我在开始节点做了个下拉选项,通过次参数进行切换","type":"text","version":1}],"direction":"ltr","format":"","indent":0,"type":"paragraph","version":1,"textFormat":0,"textStyle":""}],"direction":"ltr","format":"","indent":0,"type":"root","version":1}}' theme: blue title: '' type: '' width: 360 height: 119 id: '1742976254048' position: x: 252.70260329000598 y: 627.5 positionAbsolute: x: 252.70260329000598 y: 627.5 selected: false sourcePosition: right targetPosition: left type: custom-note width: 360 - data: authorization: config: null type: no-auth body: data: [] type: none desc: '' headers: '' method: get params: ip:{{#1742971513638.ip#}} retry_config: max_retries: 3 retry_enabled: true retry_interval: 100 selected: false timeout: max_connect_timeout: 0 max_read_timeout: 0 max_write_timeout: 0 title: HTTP 请求 type: http-request url: https://ip-moe.zerodream.net variables: [] height: 136 id: '1742976403171' position: x: 455 y: 445.5 positionAbsolute: x: 455 y: 445.5 selected: false sourcePosition: right targetPosition: left type: custom width: 244 - data: cases: - case_id: 'true' conditions: - comparison_operator: is id: c22b6065-f7d5-494e-a644-b2829ff55789 value: 工具 varType: string variable_selector: - '1742971513638' - type id: 'true' logical_operator: and desc: '' selected: false title: 条件分支(判断查询途径) type: if-else height: 126 id: '1742976553035' position: x: 180 y: 294 positionAbsolute: x: 180 y: 294 selected: false sourcePosition: right targetPosition: left type: custom width: 244 - data: author: wal desc: '' height: 114 selected: false showAuthor: true text: '{"root":{"children":[{"children":[{"detail":0,"format":0,"mode":"normal","style":"","text":"查询ip的返回结果结构结构一致,可以直接用一个参数提取器提取对应的参数","type":"text","version":1}],"direction":"ltr","format":"","indent":0,"type":"paragraph","version":1,"textFormat":0,"textStyle":""}],"direction":"ltr","format":"","indent":0,"type":"root","version":1}}' theme: blue title: '' type: '' width: 240 height: 114 id: '1742976801289' position: x: 753.7565082250148 y: 627.5 positionAbsolute: x: 753.7565082250148 y: 627.5 selected: false sourcePosition: right targetPosition: left type: custom-note width: 240 - data: author: wal desc: '' height: 112 selected: false showAuthor: true text: '{"root":{"children":[{"children":[{"detail":0,"format":0,"mode":"normal","style":"","text":"条件分支对127.0.0.1这个本机地址及192.168.1.1这样的局域网地址和网络ip地址进行拆分,实际上是为了后续的代码执行节点和模板转换节点的一个展示,这两种方案实际上效果是一致的,只是可以用两种方式来做这件事","type":"text","version":1}],"direction":"ltr","format":"","indent":0,"type":"paragraph","version":1,"textFormat":0,"textStyle":""}],"direction":"ltr","format":"","indent":0,"type":"root","version":1}}' theme: blue title: '' type: '' width: 425 height: 112 id: '1742976849815' position: x: 1113.4872135618223 y: 627.5 positionAbsolute: x: 1113.4872135618223 y: 627.5 selected: false sourcePosition: right targetPosition: left type: custom-note width: 425 - data: author: wal desc: '' height: 141 selected: false showAuthor: true text: '{"root":{"children":[{"children":[{"detail":0,"format":0,"mode":"normal","style":"","text":"通过变量聚合,来统一接受前置节点的内容,因为有分支判断,肯定只会出现一个节点的数据输出,所以用变量聚合器可以使用,如果是并行节点的话,这里用变量聚合器就不合适,会导致第二个到达的参数被弃用,只会接收第一个到达的数据","type":"text","version":1}],"direction":"ltr","format":"","indent":0,"type":"paragraph","version":1,"textFormat":0,"textStyle":""}],"direction":"ltr","format":"","indent":0,"type":"root","version":1}}' theme: blue title: '' type: '' width: 536 height: 141 id: '1742976974480' position: x: 1576.7686900958468 y: 627.5 positionAbsolute: x: 1576.7686900958468 y: 627.5 selected: false sourcePosition: right targetPosition: left type: custom-note width: 536 - data: desc: '' output_type: string selected: false title: 查询结果变量聚合器 type: variable-aggregator variables: - - '1742971521243' - text - - '1742976403171' - body height: 130 id: '1742982988677' position: x: 747.8921901299823 y: 311 positionAbsolute: x: 747.8921901299823 y: 311 selected: false sourcePosition: right targetPosition: left type: custom width: 244 viewport: x: -65.2183867047047 y: 176.2592633484365 zoom: 0.34985474669500866
最后运行的整体效果如下:点击运行,输入想要查询的ip
这个工作流做了2个分支,一个分支是使用自定义工具进行查询,另外一个分支是使用http进行查询,效果图如下:
还没有评论,来说两句吧...