Elasticsearch:智能搜索 - AI Builder 及 Workflow

想象一下,我们如何搜索如下的一个问题:

复制代码
Find a home within 10 miles of Miami, Florida that has 2 bedrooms, 2 bathrooms, central air, and tile floors, with a budget up to $300,000.

为了能够实现智能搜索,我们有几种方法来实现:

上面的这两种方案,我们都需要使用编程的技能来完成。我们有没有一种不需要编程就能完成的方法呢。答案是肯定的。我们可以为它创建一个 AI Agent。

步骤一:写入数据

我们需要按照文章 "Elasticsearch:智能搜索的 MCP" 写入文档到 Elasticsearch 中。

步骤一:创建 workflow

我们创建一个如下的 workflow:

复制代码
name: real_estate_esql_workflow
enabled: true
description: Advanced ES|QL search with Geocoding, WKT construction, and clean console output

consts:
  geocoding_api_url: https://maps.googleapis.com/maps/api/geocode/json?key=<Your API key>&

triggers:
  - type: manual

inputs:
  - name: user_query
    type: string
    required: true
    description: Natural language real estate search request

steps:
  # Step 1: Extract structured parameters from user query
  - name: extract_parameters
    type: ai.prompt
    with:
      temperature: 0.2
      outputSchema:
        type: object
        properties:
          query: { type: string }
          bathrooms: { type: integer }
          bedrooms: { type: integer }
          home_price_max: { type: number, minimum: 0 }
          property_features: { type: string }
          location: { type: string }
          distance: { type: string }
        additionalProperties: false
      prompt: |
        Extract structured real estate parameters from: {{ inputs.user_query }}

  # Step 2: Geocode the location (Restored)
  - name: get_coordinate
    type: http
    with:
      url: "{{ consts.geocoding_api_url }}address={{ steps.extract_parameters.output.content.location | url_encode }}"
      method: GET

  # Step 3: Combine parameters and normalize fields
  - name: combine_with_coordinates
    type: console
    with:
      message: |-
        {%- assign lat = steps.get_coordinate.output.data.results[0].geometry.location.lat | default: 0 -%}
        {%- assign lon = steps.get_coordinate.output.data.results[0].geometry.location.lng | default: 0 -%}
        {%- assign dist_raw = steps.extract_parameters.output.content.distance | default: "0" | replace: ' miles', '' | plus: 0 -%}
        
        {
          "query": "{{ steps.extract_parameters.output.content.query | replace: '"', '\"' | strip }}",
          "bathrooms": "{{ steps.extract_parameters.output.content.bathrooms }}",
          "bedrooms": "{{ steps.extract_parameters.output.content.bedrooms }}",
          "home_price_max": "{{ steps.extract_parameters.output.content.home_price_max }}",
          "property_features": "{{ steps.extract_parameters.output.content.property_features | replace: '"', '\"' | strip }}",
          "longitude": {{ lon }},
          "latitude": {{ lat }},
          "distance_meters": {{ dist_raw | times: 1609.34 }}
        }

  # Step 4: Build Dynamic ES|QL Query
  - name: build_esql_query
    type: console
    with:
      message: |-
        {%- assign v = steps.combine_with_coordinates.output | json_parse -%}
        {%- assign q = 'FROM properties METADATA _score | EVAL pt = TO_GEOPOINT(CONCAT("POINT(", "' | append: v.longitude | append: '", " ", "' | append: v.latitude | append: '", ")")) | EVAL distance = ST_DISTANCE(location, pt)' -%}

        {%- if v.bathrooms != "" -%}{%- assign q = q | append: " | WHERE bathrooms >= " | append: v.bathrooms -%}{%- endif -%}
        {%- if v.bedrooms != "" -%}{%- assign q = q | append: " | WHERE bedrooms >= " | append: v.bedrooms -%}{%- endif -%}
        {%- if v.home_price_max != "" -%}{%- assign q = q | append: " | WHERE home_price <= " | append: v.home_price_max -%}{%- endif -%}

        {%- if v.property_features != "" -%}
          {%- assign q = q | append: ' | WHERE MATCH(property_features, "' | append: v.property_features | append: '")' -%}
        {%- endif -%}

        {%- if v.distance_meters > 0 -%}
          {%- assign q = q | append: " | WHERE distance <= " | append: v.distance_meters -%}{%- endif -%}

        {%- if v.query != "" -%}
          {%- assign q = q | append: ' | WHERE MATCH(body_content_semantic_text, "' | append: v.query | append: '")' -%}{%- endif -%}

        {%- assign q = q | append: " | SORT _score DESC, distance ASC | LIMIT 10 | KEEP title, bedrooms, bathrooms, home_price, property_features, distance" -%}

        {{ q | strip }}

  # Step 5: Run Query
  - name: esql_run
    type: elasticsearch.esql.query
    with:
      format: json
      query: "{{ steps.build_esql_query.output | strip }}"

  # Step 6: Display Top 3 Results Nicely
  - name: display_top_results
    type: console
    with:
      message: |-
        {%- assign results = steps.esql_run.output.values -%}
        {%- if results.size == 0 -%}
        No properties found matching your criteria.
        {%- else -%}
        {%- for row in results limit:3 -%}
        Title: {{ row[0] }}
        Bathrooms: {{ row[2] }}
        Bedrooms: {{ row[1] }}
        Price: ${{ row[3] }}
        Features: {{ row[4] }}
        Distance: {{ row[5] | divided_by: 1609.34 | round: 2 }} miles

        {% endfor -%}
        {%- endif -%}

注意:上面的版本是在 9.3 上测试的。针对 9.4,我们需要把 outoutSchema 改为 schema 才可以工作。

在上面,你需要填入自己的 google API key。

测试文档如下:

复制代码
Find a home within 10 miles of Miami, Florida that has 2 bedrooms, 2 bathrooms, central air, and tile floors, with a budget up to $300,000.

我们运行的结果如下:

从上面的测试中,我们可以看到我们的查询是成功的。

步骤三:创建一个 tool

步骤四:创建一个 agent

我们需要加入上面创建的工具:

步骤五:测试

复制代码
Find a home within 10 miles of Miami, Florida that has 2 bedrooms, 2 bathrooms, central air, and tile floors, with a budget up to $300,000.
复制代码
Find a home within 10 miles of DeBary, Florida with 5 bedrooms, at least 2 bathrooms, central air, and a garage, with a budget up to $600,000.

我们完美地避开了 Python 代码的创建。

Hooray!

相关推荐
智慧景区与市集主理人4 小时前
五一乡村文旅增收难?巨有科技大数据双赋能破局突围
大数据·科技
思绪无限7 小时前
YOLOv5至YOLOv12升级:木材表面缺陷检测系统的设计与实现(完整代码+界面+数据集项目)
人工智能·深度学习·目标检测·计算机视觉·木材表面缺陷检测
kishu_iOS&AI7 小时前
深度学习 —— 损失函数
人工智能·pytorch·python·深度学习·线性回归
好运的阿财7 小时前
OpenClaw工具拆解之canvas+message
人工智能·python·ai编程·openclaw·openclaw工具
TechubNews7 小时前
新火集团首席经济学家付鹏演讲——2026 年是 Crypto 加入到 FICC 资产配置框架元年
大数据·人工智能
蒸汽求职8 小时前
跨越 CRUD 内卷:半导体产业链与算力基建下的软件工程新生态
人工智能·科技·面试·职场和发展·软件工程·制造
DeepModel8 小时前
通俗易懂讲透 Q-Learning:从零学会强化学习核心算法
人工智能·学习·算法·机器学习
Elastic 中国社区官方博客8 小时前
为 Elastic Cloud Serverless 和 Elasticsearch 引入统一的 API 密钥
大数据·运维·elasticsearch·搜索引擎·云原生·serverless
聊点儿技术8 小时前
LLM数据采集如何突破AI反爬?——用IP数据接口实现进阶
人工智能·数据分析·产品运营·ip·电商·ip地址查询·ip数据接口
小兵张健8 小时前
一场大概率没拿到 offer 的面试,让我更坚定去做喜欢的事
人工智能·面试·程序员