dify + mcp 实现图片 ocr 识别

pom.xml:

XML 复制代码
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>3.4.5</version>
        <relativePath />
    </parent>
    <groupId>com.example</groupId>
    <artifactId>mcp-server</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>Spring AI MCP Weather Sample</name>
    <description>Sample Spring Boot application demonstrating MCP client and server usage</description>

    <properties>
        <spring-cloud.version>2023.0.4</spring-cloud.version>
        <java.version>17</java.version>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <maven.compiler.source>17</maven.compiler.source>
        <maven.compiler.target>17</maven.compiler.target>
        <maven.test.skip>true</maven.test.skip>
        <easypoi.version>4.1.2</easypoi.version>
    </properties>

    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.ai</groupId>
                <artifactId>spring-ai-bom</artifactId>
                <version>1.1.0-SNAPSHOT</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>

            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>${spring-cloud.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>

    <dependencies>
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
            <version>1.2.78</version>
        </dependency>

        <dependency>
            <groupId>cn.afterturn</groupId>
            <artifactId>easypoi-base</artifactId>
            <version>${easypoi.version}</version>
        </dependency>
        <dependency>
            <groupId>cn.afterturn</groupId>
            <artifactId>easypoi-web</artifactId>
            <version>${easypoi.version}</version>
        </dependency>
        <dependency>
            <groupId>cn.afterturn</groupId>
            <artifactId>easypoi-annotation</artifactId>
            <version>${easypoi.version}</version>
        </dependency>

        <dependency>
            <groupId>org.springframework.ai</groupId>
            <artifactId>spring-ai-starter-mcp-server-webmvc</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-mail</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-redis</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.session</groupId>
            <artifactId>spring-session-data-redis</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-configuration-processor</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework.session</groupId>
            <artifactId>spring-session-core</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <optional>true</optional>
        </dependency>

        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>

        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid-spring-boot-starter</artifactId>
            <version>1.2.6</version>
        </dependency>

        <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjweaver</artifactId>
            <version>1.9.6</version>
        </dependency>

        <dependency>
            <groupId>com.github.jsqlparser</groupId>
            <artifactId>jsqlparser</artifactId>
            <version>4.9</version>
        </dependency>

        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-spring-boot3-starter</artifactId>
            <version>3.5.7</version>
        </dependency>

        <dependency>
            <groupId>com.mysql</groupId>
            <artifactId>mysql-connector-j</artifactId>
            <version>8.0.33</version>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <configuration>
                    <excludes>
                        <exclude>
                            <groupId>org.projectlombok</groupId>
                            <artifactId>lombok</artifactId>
                        </exclude>
                    </excludes>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.13.0</version>
                <configuration>
                    <source>17</source>
                    <target>17</target>
                </configuration>
            </plugin>
        </plugins>
    </build>

    <profiles>
        <profile>
            <id>dev</id>
            <properties>
                <profileActive>dev</profileActive>
            </properties>
            <activation>
                <activeByDefault>true</activeByDefault>
            </activation>
        </profile>
        <profile>
            <id>test</id>
            <properties>
                <profileActive>test</profileActive>
            </properties>
        </profile>
    </profiles>

	<repositories>
		<repository>
			<id>spring-milestones</id>
			<name>Spring Milestones</name>
			<url>https://repo.spring.io/milestone</url>
			<snapshots>
				<enabled>false</enabled>
			</snapshots>
		</repository>
		<repository>
			<id>spring-snapshots</id>
			<name>Spring Snapshots</name>
			<url>https://repo.spring.io/snapshot</url>
			<releases>
				<enabled>false</enabled>
			</releases>
		</repository>
		<repository>
			<id>central-portal-snapshots</id>
			<name>Central Portal Snapshots</name>
			<url>https://central.sonatype.com/repository/maven-snapshots/</url>
			<releases>
				<enabled>false</enabled>
			</releases>
			<snapshots>
				<enabled>true</enabled>
			</snapshots>
		</repository>
	</repositories>
</project>

application.yml:

XML 复制代码
server:
  port: 9090
spring:
  ai:
    mcp:
      server:
        version: 0.0.1
        name: my-weather-server
        #stdio: false
  #main:
  #  web-application-type: none
  #  banner-mode: off
  datasource:
    driverClassName: com.mysql.jdbc.Driver
    #driverClassName: "com.mysql.cj.jdbc.Driver"
    type: "com.alibaba.druid.pool.DruidDataSource"
    initialSize: 1
    minIdle: 3
    maxActive: 40
    maxWait: 60000
    timeBetweenEvictionRunsMillis: 60000
    minEvictableIdleTimeMillis: 30000
    validationQuery: select 'x'
    testWhileIdle: true
    testOnBorrow: false
    testOnReturn: false
    poolPreparedStatements: true
    maxPoolPreparedStatementPerConnectionSize: 20
    filters: "slf4j,stat"
    connectionProperties: "druid.stat.mergeSql=true;druid.stat.slowSqlMillis=3000"
  profiles:
    active: @profileActive@

logging:
  level:
    #org.springframework.boot: DEBUG
    org.springframework.boot: INFO
    #com.baomidou: DEBUG
    com.baomidou: INFO
  file:
    name: ./model-context-protocol/weather/starter-webmvc-server/target/starter-webmvc-server.log
  #pattern:
  # 改配置会导致 spring 工程启动后控制台没任何输出
  #  console:

mybatis-plus:
  mapper-locations: "classpath*:/mapper/*Mapper.xml"

debug: true

application-dev.yml:

XML 复制代码
spring:
  datasource:
    url: jdbc:mysql://127.0.0.1:3306/gw_image_search?useUnicode=true&characterEncoding=utf-8&useSSL=false&allowMultiQueries=true&serverTimezone=GMT%2B8&zeroDateTimeBehavior=convertToNull
    username: xxx
    password: xxx

BootApplication.java:

java 复制代码
package com.xxx.ipark.base;

import com.xxx.ipark.base.service.IOcrService;
import com.xxx.ipark.base.service.IUserService;
import com.xxx.ipark.common.config.datasource.DataSourceConfig;
import lombok.extern.slf4j.Slf4j;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.ai.tool.ToolCallback;
import org.springframework.ai.tool.ToolCallbackProvider;
import org.springframework.ai.tool.function.FunctionToolCallback;
import org.springframework.ai.tool.method.MethodToolCallbackProvider;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.data.mongo.MongoDataAutoConfiguration;
import org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration;
import org.springframework.boot.autoconfigure.mongo.MongoAutoConfiguration;
import org.springframework.boot.context.properties.ConfigurationPropertiesScan;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.core.env.Environment;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.transaction.annotation.EnableTransactionManagement;
import org.springframework.web.bind.ServletRequestUtils;

@EnableAsync
@EnableTransactionManagement
@ComponentScan(basePackages = {"com.xxx.ipark"})
@SpringBootApplication(exclude = {RedisAutoConfiguration.class,
									MongoAutoConfiguration.class,
									MongoDataAutoConfiguration.class})
@EnableConfigurationProperties( DataSourceConfig.class )
@Slf4j
public class BootApplication {

	public static void main(String[] args) {
		try {
			System.setProperty("spring.devtools.restart.enabled", "false");
			System.setProperty("es.set.netty.runtime.available.processors","false");
			ConfigurableApplicationContext application = SpringApplication.run(BootApplication.class, args);
			System.out.println( "启动成功..." );
			Environment env = application.getEnvironment();
			String applicationName = env.getProperty("spring.application.name");
			String port = env.getProperty("server.port");
			String path = env.getProperty("server.servlet.context-path");
			String ip = "";
			log.info("\n----------------------------------------------------------\n" +
					"Application " + applicationName + " is running. Access URLs:\n" +
					"Local: http://localhost:" + port + path + "/\n" +
					"External: http://" + ip + ":" + port + path + "/\n" +
					"Swagger-UI: http://" + ip + ":" + port + path + "/swagger-ui.html\n" +
					"----------------------------------------------------------");
		} catch (Exception e) {
			log.error("", e);
		}
	}

	@Bean
	public ToolCallbackProvider userTools(IUserService userService) {
		return MethodToolCallbackProvider.builder().toolObjects(userService).build();
	}

	@Bean
	public ToolCallbackProvider ocrTools(IOcrService ocrService) {
		return MethodToolCallbackProvider.builder().toolObjects(ocrService).build();
	}

	public record TextInput(String input) {
	}

	@Bean
	public ToolCallback toUpperCase() {
		return FunctionToolCallback.builder("toUpperCase", (TextInput input) -> input.input().toUpperCase())
			.inputType(TextInput.class)
			.description("Put the text to upper case")
			.build();
	}

}

DataSourceConfig.java:

java 复制代码
package com.xxx.ipark.common.config.datasource;

import com.alibaba.druid.pool.DruidDataSource;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.context.properties.ConfigurationPropertiesScan;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.boot.context.properties.bind.ConstructorBinding;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Service;

import javax.sql.DataSource;
import java.sql.SQLException;

@Data
@Slf4j
@Configuration
@ConfigurationProperties(prefix = "spring.datasource")
public class DataSourceConfig {

    private String name = "xxx";
    private String url;
    private String username;
    private String password;
    private String driverClassName;
    private int initialSize;
    private int minIdle;
    private int maxActive;
    private int maxWait;
    private int timeBetweenEvictionRunsMillis;
    private int minEvictableIdleTimeMillis;
    private String validationQuery;
    private boolean testWhileIdle;
    private boolean testOnBorrow;
    private boolean testOnReturn;
    private boolean poolPreparedStatements;
    private int maxPoolPreparedStatementPerConnectionSize;
    private String filters;
    private String connectionProperties;

    @Bean(name = "dataSource")
    @Primary
    public DataSource dataSource() {
        DruidDataSource datasource = new DruidDataSource();
        datasource.setName(name);
        datasource.setUrl(url);
        datasource.setUsername(username);
        datasource.setPassword(password);
        datasource.setDriverClassName(driverClassName);

        //configuration
        datasource.setInitialSize(initialSize);
        datasource.setMinIdle(minIdle);
        datasource.setMaxActive(maxActive);
        datasource.setMaxWait(maxWait);
        datasource.setTimeBetweenEvictionRunsMillis(timeBetweenEvictionRunsMillis);
        datasource.setMinEvictableIdleTimeMillis(minEvictableIdleTimeMillis);
        datasource.setValidationQuery(validationQuery);
        datasource.setTestWhileIdle(testWhileIdle);
        datasource.setTestOnBorrow(testOnBorrow);
        datasource.setTestOnReturn(testOnReturn);
        datasource.setPoolPreparedStatements(poolPreparedStatements);
        datasource.setMaxPoolPreparedStatementPerConnectionSize(maxPoolPreparedStatementPerConnectionSize);
        try {
            datasource.setFilters(filters);
        } catch (SQLException e) {
            log.error("Druid initialize filter failed. ", e);
        }
        datasource.setConnectionProperties(connectionProperties);
        return datasource;
    }
}

MybatisConfig.java:

java 复制代码
package com.xxx.ipark.common.config.datasource;

import com.baomidou.mybatisplus.annotation.DbType;
import com.baomidou.mybatisplus.core.MybatisConfiguration;
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
import com.baomidou.mybatisplus.extension.spring.MybatisSqlSessionFactoryBean;
import org.apache.ibatis.plugin.Interceptor;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.type.JdbcType;
import org.mybatis.spring.mapper.MapperScannerConfigurer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
import org.springframework.context.EnvironmentAware;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.env.Environment;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.transaction.annotation.EnableTransactionManagement;

import javax.sql.DataSource;
import java.util.Properties;

/**
 * Mybatis 配置文件,加入了分页器,分页器的使用:
 * com.github.pagehelper.PageHelper.startPage(1, 10);
 * List<User> list = mapper.queryUsers();
 * com.github.pagehelper.PageInfo<User> pagelist=new com.github.pagehelper.PageInfo<User>(list);
 * pageList 封装了分页列表以及其他分页相关的所有信息
 */
@Configuration( proxyBeanMethods = false )
@EnableTransactionManagement
@AutoConfigureAfter({DataSourceConfig.class})
public class MybatisConfig {
    private static final Logger logger = LoggerFactory.getLogger(MybatisConfig.class);

    @Bean(name = "sqlSessionFactoryBean")
    public SqlSessionFactory sqlSessionFactoryBean(@Qualifier("dataSource") DataSource dataSource) {
        try {
            //SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean();
            MybatisSqlSessionFactoryBean sqlSessionFactoryBean = new MybatisSqlSessionFactoryBean();
            sqlSessionFactoryBean.setDataSource(dataSource);
            // 必须添加类型别名包扫描
            sqlSessionFactoryBean.setTypeAliasesPackage("com.xxx.ipark.base.entity");

            //org.apache.ibatis.session.Configuration configuration = new org.apache.ibatis.session.Configuration();
            MybatisConfiguration configuration = new MybatisConfiguration();
            configuration.setJdbcTypeForNull(JdbcType.NULL);
            configuration.setMapUnderscoreToCamelCase(true);
            configuration.setCacheEnabled(false);
            sqlSessionFactoryBean.setConfiguration(configuration);
            // sqlSessionFactoryBean.setMapperLocations(new PathMatchingResourcePatternResolver().getResources(environment.getProperty("mybatis-plus.mapper-locations")));
            sqlSessionFactoryBean.setMapperLocations( new PathMatchingResourcePatternResolver().getResources( "classpath*:/mapper/*Mapper.xml" ) );

            Interceptor[] plugins = { this.mybatisPlusInterceptor() };
            sqlSessionFactoryBean.setPlugins(plugins);
            return sqlSessionFactoryBean.getObject();
        } catch (Exception e) {
            logger.error("", e);
        }
        return null;
    }


    @Bean(name = "transactionManager")
    public DataSourceTransactionManager testTransactionManager(@Qualifier("dataSource") DataSource dataSource) {
        return new DataSourceTransactionManager(dataSource);
    }

    @Bean
    public MapperScannerConfigurer mapperScannerConfigurer() {
        MapperScannerConfigurer mapperScannerConfigurer = new MapperScannerConfigurer();
        mapperScannerConfigurer.setSqlSessionFactoryBeanName("sqlSessionFactoryBean");
        mapperScannerConfigurer.setBasePackage("com.xxx.ipark.*.mapper");
        return mapperScannerConfigurer;
    }

    @Bean
    public MybatisPlusInterceptor mybatisPlusInterceptor() {
        MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
        interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
        return interceptor;
    }
}

CorsConfig.java:

java 复制代码
package com.xxx.ipark.common.config;

import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

// 全局配置类
@Configuration
public class CorsConfig implements WebMvcConfigurer {
    @Override
    public void addCorsMappings(CorsRegistry registry) {
        // registry.addMapping("/sse/**")  // 匹配 SSE 端点
        registry.addMapping("/**")  // 匹配 SSE 端点
                .allowedOrigins("http://localhost:63342")  // 客户端域名
                .allowedMethods("GET", "POST")
                .allowCredentials(true)  // 允许凭证(如 Cookies)
                .exposedHeaders("Content-Type", "X-Custom-Header");  // 暴露自定义头
    }
}

IOcrService.java:

java 复制代码
package com.xxx.ipark.base.service;

import com.xxx.ipark.base.entity.UserEntity;

public interface IOcrService {
    String driversLicenseOcr( String driversLicenseImageUrl );
}

OcrServiceImpl.java:

java 复制代码
package com.xxx.ipark.base.service.impl;

import com.xxx.ipark.base.entity.UserEntity;
import com.xxx.ipark.base.service.IOcrService;
import org.springframework.ai.tool.annotation.Tool;
import org.springframework.stereotype.Service;

@Service
public class OcrServiceImpl implements IOcrService {

    @Tool( description = "个人驾驶证图片ocr识别(该方法请求参数 driversLicenseImageUrl 是 String 类型,表示用户上传的驾驶证的图片的 url 地址)")
    @Override
    public String driversLicenseOcr(String driversLicenseImageUrl) {
        // todo 换成调用大厂的 ocr api
        System.out.println( "call driversLicenseOcr with param driversLicenseImageUrl = " + driversLicenseImageUrl );
        return "驾驶员姓名:张三风,驾照生效开始日期:2024-01-01,驾照生效结束日期:2025-01-01,车牌号:京A-88888";
    }
}

dify 上安装如下所示的 mcp 工具和 agent 策略插件:

dify 开始节点:

dify agent 节点-part1:

dify agent 节点-part2:

结束节点:

完整工作流概览:

测试:

输出:

返回的是我们代码里 mock 的数据,可以修改下代码,调用大厂的 ocr 接口。

下面我们换成直接调用百度的个人证照识别的 mcp 服务:

例如使用百度的 个人证照识别 mcp 服务

将dify 工作流中的 mcp 地址换成 如下:

XML 复制代码
 {
	"server_name": {
		"url": "https://aip.baidubce.com/mcp/ocr_personal_card/sse?Authorization=Bearer%20xxxxxxxxxxxxxx",
		"headers": {"Content-Type":"application/json"},
		"timeout": 50,
		"sse_read_timeout": 50
	}
}

测试后结果如下:

应该通了,这个是百度ocr接口返回的错误信息。

查看 agent 节点的详细输出:

拷贝出来发现包含如下信息:

XML 复制代码
"<think>\n\n好的,用户上传了一个驾驶证图片的URL,需要我来处理。
						首先,我要确定用户的需求是什么。他们可能想通过OCR识别驾驶证上的信息,比如姓名、证号、有效期等。
						根据提供的工具列表,ocr_driving_license  这个函数是专门用来处理驾驶证的。
						\n\n接下来,我需要检查这个函数的参数。
						ocr_driving_license的参数包括image、url、detect_direction、driving_license_side等。
						用户提供的只是一个URL,所以应该使用url参数。
						需要注意的是,当image存在时,url会被忽略,但这里用户只给了URL,没有提供image数据,所以应该正确传递url参数。
						\n\n然后,确认其他参数是否有默认值。例如,driving_license_side默认是front,即识别正页。
						如果用户提供的图片是副页,可能需要调整这个参数,但用户没有说明,所以保持默认。
						同样,detect_direction默认是false,不检测方向,除非用户提到图片可能旋转,但这里也没有相关信息,所以保持默认。
						\n\n还要注意函数的限制条件,比如URL对应的图片大小不能超过10M,分辨率符合要求。
						用户提供的URL看起来是有效的,所以直接调用函数即可。
						不需要其他参数,除非用户有特殊要求,但这里没有提到,所以只需要传递url参数。
						\n\n综上所述,调用ocr_driving_license函数,参数中填入提供的URL,其他参数使用默认值。
						这样就能正确识别驾驶证的信息返回给用户了。
						\n\n
	       </think>\n\n
		   <think>\n\n好的,用户刚才上传了一个驾驶证图片的URL,我调用了ocr_driving_license工具来处理。
					但是返回了一个错误,说QPS请求限制达到了。
					现在需要想想怎么解决这个问题。
					\n\n首先,用户的需求是识别驾驶证图片,所以必须找到其他方法来处理。可能的问题在于当前使用的工具访问量太大,被限制了。
					这时候应该看看有没有其他类似功能的工具可以使用。
					例如,如果用户可以上传图片数据而不是URL的话,或者如果有备用的API端点,或者是否有其他服务可以处理。
					\n\n检查可用的工具列表,有没有其他相关的OCR功能。比如,用户有提到过是否还有其他工具支持驾驶证识别。
					例如,可能还有另一个版本的OCR驾驶执照工具,或者是否有其他类似的工具。
					不过根据原先提供的工具列表里,ocr_driving_license似乎是唯一的驾驶证识别工具。
					\n\n这时候可能需要考虑是否可以直接让用户将图片转换为base64并再次尝试调用,
					但用户目前是通过URL提交的,所以可能需要更替其他方式,但用户可能无法立即提供base64编码的数据。
					或者是否可以设置一个服务器配置(servers_config)来指定备用服务,但工具的具体参数可能需要进一步确认。
					\n\n查看mcp_sse_call_tool的参数,需要tool_name和arguments。是否有其他工具名称可以调用?
					例如是否有备用的路径或不同的服务实例。或者是否可以汇总其他工具,但用户已经看到提供的工具中并没有其他驾驶证工具。
					所以可能需要告知用户当前达到限流,需要重试或联系管理员处理。
					但如果用户需要即时解决,可能需要其他途径,例如更换API配置,但缺乏相关参数。
					\n\n可能的话,可以尝试调用其他可用工具吗?比如是否有其他支持驾驶证的OCR服务,但根据给定的工具列表中没有其他工具。
					这时候,可能需要向用户说明无法继续,并建议稍后再试或检查他们的上传方式是否有误。
					也可能用户需要切换到base64上传,但用户可能无法立即处理。\
					n\n因此,最终的回应应该是告知用户当前系统达到请求上限,建议稍后再试,或者由他们提供base64编码的图片数据以便使用备用方法。
					不过根据用户目前的情况,可能无法提供更多数据,所以应该确认错误并提供相关的解决方案。
		\n\n</think>
		\n\n当前识别服务达到请求上限,请稍后再试或联系管理员提升配额。
		若需立即处理,可提供证件头像区域截图或base64编码,我将尝试调用备用通道进行识别。",

可以看出大模型思考过程中说 "ocr_driving_license 这个函数是专门用来处理驾驶证的",函数 "ocr_driving_license " 在百度个人证照识别下确实存在,如下所示:

进入 ocr_driving_license(驾驶证识别) 的文档:

发现大模型思考过程中对 ocr_driving_license函数如下所示的分析:

XML 复制代码
ocr_driving_license 的参数包括image、url、detect_direction、driving_license_side等。
用户提供的只是一个URL,所以应该使用url参数。
需要注意的是,当image存在时,url会被忽略,但这里用户只给了URL,没有提供image数据,所以应该正确传递url参数。
\n\n然后,确认其他参数是否有默认值。例如,driving_license_side默认是front,即识别正页。
如果用户提供的图片是副页,可能需要调整这个参数,但用户没有说明,所以保持默认。
同样,detect_direction默认是false,不检测方向,除非用户提到图片可能旋转,但这里也没有相关信息,所以保持默认。
\n\n还要注意函数的限制条件,比如URL对应的图片大小不能超过10M,分辨率符合要求。
用户提供的URL看起来是有效的,所以直接调用函数即可。

也基本符合驾驶证识别接口的请求参数说明,这就证明是调通了,只是没配额了。有条件的可以充值测试一下。

相关推荐
think12337 分钟前
带你走进Spring Cloud的世界
spring boot·后端·spring cloud
泉城老铁2 小时前
Spring Boot 应用打包部署到 Tomcat ,如何极致调优看这里
java·spring boot·后端
r0ad2 小时前
LLMs.txt:AI时代网站的"智能身份证"
llm
DisonTangor3 小时前
小红书开源dots.ocr:单一视觉语言模型中的多语言文档布局解析
语言模型·开源·ocr
℡余晖^3 小时前
每日面试题20:spring和spring boot的区别
java·spring boot·spring
没有bug.的程序员4 小时前
《Spring Boot应用工程化提升:多模块、脚手架与DevTools》
java·运维·spring boot
摘星编程4 小时前
MCP革命:Anthropic如何重新定义AI与外部世界的连接标准
人工智能·ai·anthropic·mcp·ai连接标准
测试者家园4 小时前
Browser-Use在UI自动化测试中的应用
自动化测试·软件测试·人工智能·llm·ui自动化测试
长安城没有风4 小时前
从 0 到 1 认识 Spring MVC:核心思想与基本用法(上)
java·spring boot·spring·java-ee·mvc