D02.从0到1实现一个自然语言提取地址信息的智能体

一灰灰blogSpringAISpringSpringAI约 5722 字大约 19 分钟

大概两年之前,我们有一个快递类型的业务场景,为了简化用户的操作,为用户提供了一个快捷功能,支持用户直接粘贴一段自然语言的文本,然后由程序后台基于这段文本自动提取出结构化的地址信息,在方式大模型还未普及,我们使用的是baidu的一个收费接口

虽然价格不贵,但总归也是收费不是;这个场景非常垂直聚焦,正好也可以作为我们应用集成LLM的一个实验田。接下来我将介绍下如何利用 Spring AI 框架结合大模型能力,实现从自然语言文本中自动提取结构化地址信息的完整方案,并且通过function call实时查询行政编码,从而打造一个完整可直接商用的 “地址提取智能体”

一、整体架构设计

1.1 技术栈选型

  • SpringAI 1.1.2:统一AI调用框架
  • ZhiPu:使用它的免费版大模型 GLM-4-Flash
  • Function Calling:让大模型具备调用外部API的能力
  • SpringBoot 3.x:现代化Java框架
  • JDK17+: java版本最低要求17
  • 行政区划编码库Administrative-divisions-of-Chinaopen in new window

1.2 系统架构

从整体的视角来看,这个地址信息的提取结构相对清晰,基于用户输入的自然语言、通过LLM获取结构化的地址信息,然后返回给用户;

结合应用程序对地址的使用策略,我们在基本中文地址提取之外,通过Function Calling机制,实现让大模型返回的结构化信息中,包含行政区域代码,这样更方便将大模型返回的地址信息与项目中自己维护的地址信息进行映射;

说明:返回行政区域编码,主要是为了避免出现 本地地址库中存 湖北省、武汉市,但是大模型返回的是 湖北、武汉 这类文本,导致后台程序无法精确根据地址文本进行映射的场景;通过统一的行政区域编码,则可以有效规避这种场景

下面是整体的结构图

flowchart TB
    %% 样式定义:按功能分类,延续系列配色体系
    classDef inputNode fill:#e1f5fe,stroke:#0288d1,stroke-width:2px,rounded:10px,font-size:13px
    classDef subgraphNode fill:#fafafa,stroke:#9c27b0,stroke-width:2px,rounded:10px
    classDef coreNode fill:#fce4ec,stroke:#c2185b,stroke-width:2px,rounded:10px,font-size:13px
    classDef logicNode fill:#f3e5f5,stroke:#9c27b0,stroke-width:2px,rounded:10px,font-size:13px
    classDef funcNode fill:#ffe0b2,stroke:#ef6c00,stroke-width:2px,rounded:10px,font-size:13px
    classDef outputNode fill:#e8f5e8,stroke:#388e3c,stroke-width:2px,rounded:10px,font-size:13px
    classDef noteNode fill:#fafafa,stroke:#bdbdbd,stroke-dasharray:3 3,rounded:8px,font-size:12px

    %% 起始节点:用户输入
    input["用户输入自然语言地址<br/>Input: Natural Language Address<br/>(如:北京市朝阳区XX街XX小区)"]:::inputNode

    %% 核心子模块:SpringAI 智能地址解析器
    subgraph SpringAI智能地址解析器SpringAI Address Parser
        style 地址提取智能体 fill:#fcf1f7,stroke:#c2185b,stroke-width:3px,rounded:10px
        prompt["Prompt 工程 + 结构化输出约束<br/>Prompt Engineering<br/>(强制返回:省/市/区/街/门牌)"]:::coreNode
    end

    %% 中间处理节点
    structAddr["结构化地址信息<br/>Structured Address Info<br/>(标准化地址分段格式)"]:::logicNode
    funcCall["Function Call<br/>行政区划编码查询<br/>(从地址库获取行政编码)"]:::funcNode

    %% 最终输出节点
    output["标准化地址输出<br/>Standardized Address Output<br/>+ 行政区域编码<br/>(符合国标GB/T 2260格式)"]:::outputNode

    %% 流程连接:强化链路逻辑
    input -->|解析请求| prompt
    prompt -->|地址分段结果| structAddr
    prompt -->|编码查询触发| funcCall
    structAddr -->|整合| output
    funcCall -->|编码结果| output

    %% 核心注解:点明流程价值
    note[📌 核心逻辑:通过 Prompt 约束+Function Call 实现自然语言地址→标准化地址+行政编码的转化]:::noteNode
    prompt -.-> note

    %% 箭头样式:强化链路区分
    linkStyle 0 stroke:#616161,stroke-width:1.5px
    linkStyle 1 stroke:#c2185b,stroke-width:1.5px
    linkStyle 2 stroke:#c2185b,stroke-width:1.5px
    linkStyle 3 stroke:#388e3c,stroke-width:1.5px
    linkStyle 4 stroke:#388e3c,stroke-width:1.5px

二、核心实现步骤

首先我们需要搭建要给SpringAI的项目,不太熟悉的小伙伴可以参照 01.创建一个SpringAI的示例工程 | 一灰灰的站点open in new window 来完成

在下面的实现过程中,我们使用智谱的免费大模型作为我们的实际载体;若希望使用其他的模型的小伙伴,也可以直接替换(SpringAI对不同厂商的大模型集成得相当可以,切换成本较低)

2.1 环境配置与依赖

我们使用的SpringAI的版本为最新的 1.1.2 ,此外直接使用 zhipu 的starter来作为大模型的交互客户端

<!-- pom.xml 关键依赖 -->
<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.ai</groupId>
        <artifactId>spring-ai-starter-model-zhipuai</artifactId>
    </dependency>
</dependencies>

然后在配置文件中,设置对应的配置信息,其中关键点为

  • api-key: 可以通过启动参数、系统环境变量等方式注入key,从而避免硬编码导致的泄露问题
  • model: 选择的是免费的 GLM-4-Flash, 支持 function call (说明:若你选中的模型不支持函数调用,那么就无法实现后续的行政区域查询的工具注入)
# application.yml
spring:
  ai:
    zhipuai:
      # api-key 使用你自己申请的进行替换;如果为了安全考虑,可以通过启动参数进行设置
      api-key: ${zhipuai-api-key}
      chat:
        options:
          model: GLM-4-Flash


# 修改日志级别
logging:
  level:
    org.springframework.ai.chat.client.advisor.SimpleLoggerAdvisor: debug

2.2 地址数据结构设计

首先定义一下我们希望接受的结构化返回数据,以常见的快递物流的地址信息为例,关键信息包含:

  • 街道
  • 详细地址
  • 用户
  • 手机号
record Address(
        @JsonPropertyDescription("省,如 湖北省")
        String province,
        @JsonPropertyDescription("市,如 武汉市")
        String city,
        @JsonPropertyDescription("区,如 武昌区")
        String area,
        @JsonPropertyDescription("街道,如 东湖路")
        String street,
        @JsonPropertyDescription("行政区域编码,如 420106")
        String adCode,
        @JsonPropertyDescription("详细地址,如 发财无限公司8栋8单元888号")
        String detailInfo,
        @JsonPropertyDescription("联系人,如 张三")
        String personName,
        @JsonPropertyDescription("联系人电话,如 15345785872")
        String personPhone
) {
}

2.3 快速原型实现

接下来我们看一下直接使用大模型本身的文本提取能力,快速实现一个基础的原型

@RestController
public class ChatController {
    private final ChatModel chatModel;

       @Autowired
    public ChatController(ChatModel chatModel) {
        this.chatModel = chatModel;
    }

    /**
     * 从传入的自然语言中,提取出地址信息
     *
     * @param content
     * @return
     */
    @GetMapping("/ai/genAddress")
    public Address generateAddress(String content) {
        BeanOutputConverter<Address> beanOutputConverter = new BeanOutputConverter<>(Address.class);
        String format = beanOutputConverter.getFormat();


        PromptTemplate template = new PromptTemplate("请从下面个你的文本中,帮我提取详细的地址信息,要求中文返回: \n\n地址信息:\n{area} \n\n返回格式:{format}");
        Prompt prompt = template.create(Map.of("area", content, "format", format));
        Generation generation = chatModel.call(prompt).getResult();
        if (generation == null) {
            return null;
        }
        return beanOutputConverter.convert(generation.getOutput().getText());
    }
}

在上面的实现中,我们直接使用 ChatModel 进行大模型的交互,在这不到10行的代码中,主要使用到两个技术点

  • 提示词模板: PromptTemplate 实现占位替换
  • 结果化返回: 通过BeanOutputConverter实现bean对象转json schema,然后通过提示词工程约束大模型返回;同时也通过Converter实现返回结果转Bean对象

接下来看一下试验效果

# 用于测试的文本,示例来源于 https://ai.baidu.com/tech/nlp_apply/address

礼盒20个吉林省长春市朝阳区开运街领秀朝阳小区 田甜 18692093383

玲 18682085605 广州市天河区迎福路527号广东金融学院

从上面的实际表现也可以看出,有两个明显的问题

  • 行政区域编码返回的不一定准确:如上面的 长春市朝阳区 的行政区域编码返回就不对
  • 详细地址提取不一定准确:上图中广州市的这个地址,两次请求的返回不一样,且结果不完整

从这个快速原型我们也可以看出,基于大模型做地址识别方向可行,但是还需要“调教” ———— 即需要有一个更稳定、高质量输出的提示词设计

2.4 Prompt工程:引导模型输出的准确的结果

上面demo中的提示词过于简略,因此我们需要设计一个更符合工程化的提示词(有兴趣的小伙伴可以查看 大模型应用开发系列教程: 第五章 从 Prompt 到 Prompt 模板与工程治理open in new window 看看如何设计更推荐的提示词)

由于这个场景的目标非常清晰,所以对应的设计可以从下面几个出发

  • 角色:地址信息提取专家
  • 约束:一些地址相关的提取规则
  • 结构化:返回的定义
  • 少样本学习:提供示例,用于少样本学习

然后在上面的基础上,我们改造一下具体的实现策略

@RestController
public class ChatController {
    
    private static final String SYSTEM_PROMPT = """
        你是一个专业的地址信息提取专家。请从用户输入的自然语言文本中提取结构化地址信息。
                
        提取规则:
        1. 识别并分离出:省份、城市、区县、街道、详细地址
        2. 地址组件可能存在简称、别称,请转换为标准名称
        3. 如果用户输入包含"省"、"市"、"区"、"县"等关键词,需正确处理
                
        输出格式要求:
        - 省份:完整省份名称,如"广东省"
        - 城市:地级市名称,直辖市填"北京市"等
        - 区县:区或县级市名称
        - 街道:街道、乡镇名称
        - 详细地址:门牌号、小区、楼栋等
        - 行政区域编码:通常是区县一级的编码,6位数字
                
        示例输入:"礼盒20个吉林省长春市朝阳区开运街领秀朝阳小区 田甜 18692093383"
        示例输出: {
            "province": "吉林省",
            "city": "长春市",
            "area": "朝阳区",
            "street": "开运街领秀朝阳小区",
            "adCode": "220104",
            "personName": "田甜",
            "personPhone": "18692093383"
        }
        """;
    
    private final ChatModel chatModel;

    private final ChatClient chatClient;

    @Autowired
    public ChatController(ChatModel chatModel) {
        this.chatModel = chatModel;
        this.chatClient = ChatClient.builder(chatModel)
                .defaultAdvisors(new SimpleLoggerAdvisor(ModelOptionsUtils::toJsonStringPrettyPrinter, ModelOptionsUtils::toJsonStringPrettyPrinter, 0))
                .defaultSystem(SYSTEM_PROMPT)
                .build();
    }

    @GetMapping("/ai/genAddressWithPromptTemplate")
    public Address generateAddressWithPromptTemplate(String content) {
        ChatClient.CallResponseSpec res = chatClient.prompt(content).call();
        Address address = res.entity(Address.class);
        return address;
    }
}

在这个实现中,我们直接提取了一个提示词模板 SYSTEM_PROMPT (虽然上面的代码是直接硬编码的方式写成的,但是更推荐的是使用更专业的提示词管理服务来维护、比如支持版本、灰度对比等)

其次就是具体的LLM交互中,我们使用 ChatClient 替换了更原生的 ChatModel,因为它对系统提示词、结构化返回从使用角度封装得更友好,使用起来更简单;从代码量也可以看出,三行就完前面同等的调用过程

同样的我们来看看具体表现,依然使用前面的测试文本

从上面的结果来看,广州市这个文本的详细地址解析就稳定可靠多了;但是吉林这个地址行政区域编码错误的问题依旧,显然提示词本身是无法纠正大模型的错误资料库的

所以接下来我们就需要给大模型安上“作弊器”,让它有能力查询到正确的行政区域编码

2.5 Function Call实现:行政区划编码查询

虽然有一些API提供了行政区域编码(比如高德),但是为了减少外部依赖(当然也是为了白嫖),我们选择使用标准的行政编码库来提供自己的查询服务

首先是从开源项目中获取数据集:https://github.com/modood/Administrative-divisions-of-Chinaopen in new window

为了准确性,我们选择的是 pca-code.json 这个包含 省、市、区 三级联动的数据库(因为街道的变动频率相比较于这三级高太多了...)

这个字典的数据模型形如

[
    {
        "code": "11",
        "name": "北京市",
        "children": [
            {
                "code": "1101",
                "name": "市辖区",
                "children": [
                    {
                        "code": "110101",
                        "name": "东城区"
                    },
                    {
                        "code": "110102",
                        "name": "西城区"
                    }
                ]
            }
        ]
    }
]

因此我们可以实现一个简单基于内存的行政区域查询服务

  • 读取字典、映射为结构化数据
  • 解析为Map格式,方便快速查找

下面就是一个基础的初始化实现过程(阅读起来有困难的小伙伴不妨结合AICoding解释一下)

@Service
public class AddressAdCodeService {
    private final Logger log = org.slf4j.LoggerFactory.getLogger(AddressAdCodeService.class);
    private final static String data = "data/pca-code.json";

    private volatile Map<String, ProvinceMapper> provinceMap;

    /**
     * 从 data/pca-code.json 中加载数据,并结构化
     */
    @PostConstruct
    public void init() {
        try (InputStream stream = this.getClass().getClassLoader().getResourceAsStream(data)) {
            // 读取数据
            String content = IOUtils.toString(stream, UTF_8);
            ObjectMapper mapper = new ObjectMapper();
            // 将content反序列化为 List<Province>
            List<Province> provinces = mapper.readValue(content, mapper.getTypeFactory().constructCollectionType(List.class, Province.class));

            // 构建结构化数据,方便快速查找
            HashMap<String, ProvinceMapper> map = new HashMap<>();
            for (Province province : provinces) {
                ProvinceMapper provinceMap = new ProvinceMapper(province.code, province.name, new HashMap<>());
                map.put(province.name, provinceMap);
                for (City city : province.children) {
                    Map<String, Area> areaMap = CollectionUtils.isEmpty(city.children) ? Map.of() : city.children.stream().collect(Collectors.toMap(s -> s.name, s -> s));
                    CityMapper cityMap = new CityMapper(city.code, city.name, areaMap);
                    provinceMap.children.put(city.name, cityMap);
                }
            }
            this.provinceMap = map;
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    public record Area(String code, String name) {
    }


    public record City(String code, String name, List<Area> children) {
    }

    public record CityMapper(String code, String name, Map<String, Area> children) {
    }

    public record Province(String code, String name, List<City> children) {
    }

    public record ProvinceMapper(String code, String name, Map<String, CityMapper> children) {
    }
}

让后就是提供查询服务,并通过SpringAI 的 @Tool 注解来声明为大模型的回调工具

// 同样在 AddressAdCodeService.java 类中

/**
 * 查询地址对应的行政编码
 *
 * @param province 省
 * @param city     市
 * @param area     区
 * @return 行政编码
 */
@Tool(description = "传入地址信息,返回对应的行政区域编码, 如输入 湖北省武汉市武昌区,返回的行政编码为 420106")
public String queryAdCode(
        @ToolParam(description = "省,如 湖北省")
        String province,
        @ToolParam(description = "市,如 武汉市")
        String city,
        @ToolParam(description = "区,如 武昌区")
        String area) {
    log.info("queryAdCode: {}, {}, {}", province, city, area);
    ProvinceMapper provinceMap = this.provinceMap.get(province);
    if (StringUtils.isBlank(city)) {
        return provinceMap.code;
    }
    CityMapper cityMap = provinceMap.children.get(city);
    if (cityMap == null) {
        // 市未查到,返回省的行政编码
        return provinceMap.code;
    }
    if (StringUtils.isBlank(area)) {
        return cityMap.code;
    }

    Area ar = cityMap.children.get(area);
    if (ar == null) {
        // 区未查到,返回市的编码
        return cityMap.code;
    }
    return ar.code;
}

2.6 完全体智能地址提取

上面虽然实现了行政区域查询服务,但是还需要把它提供给大模型使用,这一步我们需要怎么做呢?

看下面的实现,你会发现这个改动非常简单,只需两步:

  • 调整提示词约束:要求大模型必须通过提供的工具来获取行政区域编码
  • 注册工具

@RestController
public class ChatController {

  // 注意下面提取规则中的第四点,就是我们新增的约束
  private static final String SYSTEM_PROMPT = """
            你是一个专业的地址信息提取专家。请从用户输入的自然语言文本中提取结构化地址信息。
                    
            提取规则:
            1. 识别并分离出:省份、城市、区县、街道、详细地址
            2. 地址组件可能存在简称、别称,请转换为标准名称
            3. 如果用户输入包含"省"、"市"、"区"、"县"等关键词,需正确处理
            4. 行政区域编码必须使用提供的工具 queryAdCode 进行获取
                    
            输出格式要求:
            - 省份:完整省份名称,如"广东省"
            - 城市:地级市名称,直辖市填"北京市"等
            - 区县:区或县级市名称
            - 街道:街道、乡镇名称
            - 详细地址:门牌号、小区、楼栋等
            - 行政区域编码:通常是区县一级的编码,6位数字
                    
            示例输入:"礼盒20个吉林省长春市朝阳区开运街领秀朝阳小区11栋2号楼304 田甜 18692093383"
            示例输出: {
                "province": "吉林省",
                "city": "长春市",
                "area": "朝阳区",
                "street": "开运街领秀朝阳小区",
                "detailInfo": "11栋2号楼304",
                "adCode": "220104",
                "personName": "田甜",
                "personPhone": "18692093383"
            }
            """;

    private final ChatModel chatModel;

    private final ChatClient chatClient;

    private final AddressAdCodeService addressAdCodeService;

    @Autowired
    public ChatController(ChatModel chatModel, AddressAdCodeService addressAdCodeService) {
        this.chatModel = chatModel;
        this.addressAdCodeService = addressAdCodeService;
        this.chatClient = ChatClient.builder(chatModel)
                .defaultAdvisors(new SimpleLoggerAdvisor(ModelOptionsUtils::toJsonStringPrettyPrinter, ModelOptionsUtils::toJsonStringPrettyPrinter, 0))
                .defaultSystem(SYSTEM_PROMPT)
                .build();
    }

    @GetMapping("/ai/genAddressWithCodeTool")
    public Address generateAddressWithCodeTool(String content) {
        // 直接使用 tools() 来注册大模型回调的工具 
        ChatClient.CallResponseSpec res = chatClient.prompt(content).tools(addressAdCodeService).call();
        Address address = res.entity(Address.class);
        return address;
    }
}

再次试验一下实际表现

2.7 整体流程

接下来我们从整体的视角回归一下这个智能地址提取的全流程,其中相关的技术点为

  • 提示词工程
  • 结构化返回
  • Function Call工具调用
flowchart TD
    A[用户输入自然语言地址] --> B{地址解析智能体}
    
    B --> C[Prompt工程优化]
    C --> D[调用大语言模型]
    D --> F[提取结构化地址]
    
    F --> H[生成标准化地址]
    F --> I[通过Function Call<br>查询行政编码]
    
    I --> J{编码查询结果?}
    J -->|成功| K[获取行政区域编码]
    J -->|失败| L[使用默认编码]
    
    K --> M[组装完整结果]
    L --> M
    
    M --> N[输出标准化地址<br>+行政编码]
    
    style A fill:#e1f5fe,stroke:#01579b
    style B fill:#bbdefb,stroke:#0d47a1,stroke-width:2px
    style D fill:#f3e5f5,stroke:#4a148c
    style F fill:#c8e6c9,stroke:#2e7d32
    style I fill:#fff3e0,stroke:#e65100
    style K fill:#d1c4e9,stroke:#4527a0
    style M fill:#fce4ec,stroke:#ad1457
    style N fill:#e8f5e8,stroke:#1b5e20,stroke-width:2px

三、生产优化及部署

3.1 调参:稳定性输出

在实际的生产体验过程中,我们大概率会发现,同样一段自然语言,大模型提取的详细地址这块,可能并不总是相同的,why?

对于省市区这三个相对来说比较固定的地址信息,对于街道门牌号的可能性实在是太多,大模型中有一个参数 temperature 它会控制大模型预测结果的倾向,对此有兴趣的小伙伴可以参照 大模型应用开发系列教程:第二章 模型不是重点,参数才是你真正的控制面板open in new window

在我们这个场景下,很明显不希望大模型自由发挥,所以我们可以将temperature设置较低,确保输出结果稳定

我们需要修改的就是配置文件中的spring.ai.zhipuai.chat.options.temperature,如下

spring:
  ai:
    zhipuai:
      # api-key 使用你自己申请的进行替换;如果为了安全考虑,可以通过启动参数进行设置
      api-key: ${zhipuai-api-key}
      chat:
        options:
          model: GLM-4-Flash
          temperature: 0.2

3.2 Docker容器化部署

# Dockerfile
FROM openjdk:17-jdk-slim
WORKDIR /app
COPY target/D03-text-address-extraction-0.0.1-SNAPSHOT.jar app.jar
EXPOSE 8080
ENTRYPOINT ["java", "-jar", "app.jar", 
            "--spring.ai.zhipuai.api-key=${ZHIPU_KEY}"]

3.3 Kubernetes部署配置

# deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: address-agent
spec:
  replicas: 3
  template:
    spec:
      containers:
      - name: address-agent
        image: address-agent:1.0.0
        env:
        - name: OPENAI_KEY
          valueFrom:
            secretKeyRef:
              name: ai-secrets
              key: api-key
        resources:
          requests:
            memory: "512Mi"
            cpu: "250m"
          limits:
            memory: "1Gi"
            cpu: "500m"
        readinessProbe:
          httpGet:
            path: /actuator/health
            port: 8080

四、小结

4.1 智能体 or NO?

从上到下顺下来,我们的智能地址提取基本已经完成,从本质上来说,这是一个大模型的能力包装服务,那么它算“智能体”吗?

好像也不太算,哪个智能体这么简单呢🤣

但若从下面这些角度出发,它又算是一个非常垂直的工具增强型智能体:

  1. 目标导向:用户输入的是自然语言目标——“从这段文字里提取地址并查清楚它的行政区划编码”,而不是“先调用NLP模型解析,再用结果里的省市去查XX API”。
  2. 自主规划与推理:系统内部自动完成了规划:① 识别出这是地址提取任务 -> ② 调用LLM进行结构化解析 -> ③ 判断是否需要并请求行政编码 -> ④ 调用外部函数获取编码 -> ⑤ 整合结果。这个决策链条是智能体自主生成的
  3. 核心工具使用:其核心能力 Function Calling 正是智能体的标志性特征。LLM作为“大脑”,决定使用 queryAdCode 这个“工具”(手或脚)。
  4. 可扩展的交互与记忆:虽然当前版本可能是单次查询,但它很容易扩展为多轮对话。例如,用户说“地址不对,我指的是杭州的西湖区”,智能体可以记住上下文,重新查询。

对比一个非智能体的传统方案:

一个传统的地址解析服务可能提供一个复杂的API表单,要求用户自己先分词,然后分别填写provincecitydistrict等字段来查询编码。

用户承担了所有的规划和推理工作;而这个智能地址提取,就很“智能”了

4.2 特点

最后针对本文的内容,整体小结一下:通过本文介绍的方案,我们构建了一个端到端的智能地址解析系统,具备以下特点:

  1. 自然语言理解:利用大模型处理各种自由格式的地址输入
  2. 提示词模板:通过构建结构化的提示词管理,提高大模型的返回质量
  3. 结构化输出:确保输出符合标准化要求
  4. 实时编码查询:通过function call动态获取行政区域编码

4.3 未来扩展方向:

  1. 多模型支持:集成本地化大模型降低API成本
  2. 地址补全与纠错:对不完整或错误地址进行智能修正
  3. 国际化支持:处理多语言地址解析
  4. GIS集成:结合地理信息系统提供坐标映射
  5. 实时更新:自动同步最新的行政区划变更

通过一个简单的场景,不到200行代码,实现一个“地址提取智能体”,给大家提供一个关于大模型应用开发的案例;当然本篇内容也是作为理论科普系列教程的实战篇,强烈建议对大模型应用开发感兴趣的小伙伴,看看以下几篇内容(每篇耗时不超过五分钟😊)

Loading...