DeepSeek funcation call尝试

本文主要尝试一下ollama + deepseek-r1的function call。

步骤

自定义function

@Service
@Slf4j
@Description("根据用户的查询生成天气相关信息")
public class DemoFunction implements Function<DemoFunction.Request, DemoFunction.Response> {

    @JsonClassDescription("用户的查询")
    public record Request(
            @JsonProperty(required = true,
                    value = "query") @JsonPropertyDescription("用户的查询") String query){
    }

    @JsonClassDescription("天气信息")
    public record Response(String result) {
    }

    @Override
    public Response apply(Request s) {
        log.info("call demoFunction query:{}", s.query);
        return new Response("今天深圳天气晴朗");
    }
}

api调用

    @GetMapping("/function-all")
    public String functionCall(HttpServletResponse response, @RequestParam("query") String query) {
        response.setCharacterEncoding("UTF-8");
        OllamaOptions customOptions = OllamaOptions.builder()
                .topP(0.7)
                .temperature(0.8)
                .function("demoFunction")
                .build();
        return ollamaChatModel.call(new Prompt(Arrays.asList(new SystemMessage("请基于用户的查询调用function来回答"), new UserMessage(query)), customOptions)).getResult().getOutput().getContent();
    }

执行http://localhost:10005/ollama/chat-model/function-all?query=今天天气怎么样,发现报错registry.ollama.ai/library/deepseek-r1:8b does not support tools

2025-02-21T17:45:28.633+08:00 ERROR 26728 --- [spring-ai-alibaba-ollama-chat-model-example] [io-10005-exec-1] o.a.c.c.C.[.[.[/].[dispatcherServlet]    : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed: java.lang.RuntimeException: [400] Bad Request - {"error":"registry.ollama.ai/library/deepseek-r1:8b does not support tools"}] with root cause

java.lang.RuntimeException: [400] Bad Request - {"error":"registry.ollama.ai/library/deepseek-r1:8b does not support tools"}
    at org.springframework.ai.ollama.api.OllamaApi$OllamaResponseErrorHandler.handleError(OllamaApi.java:278) ~[spring-ai-ollama-1.0.0-M5.jar:1.0.0-M5]
    at org.springframework.web.client.ResponseErrorHandler.handleError(ResponseErrorHandler.java:63) ~[spring-web-6.2.0.jar:6.2.0]
    at org.springframework.web.client.StatusHandler.lambda$fromErrorHandler$1(StatusHandler.java:71) ~[spring-web-6.2.0.jar:6.2.0]
    at org.springframework.web.client.StatusHandler.handle(StatusHandler.java:146) ~[spring-web-6.2.0.jar:6.2.0]
    at org.springframework.web.client.DefaultRestClient$DefaultResponseSpec.applyStatusHandlers(DefaultRestClient.java:823) ~[spring-web-6.2.0.jar:6.2.0]
    at org.springframework.web.client.DefaultRestClient$DefaultResponseSpec.lambda$readBody$4(DefaultRestClient.java:812) ~[spring-web-6.2.0.jar:6.2.0]
    at org.springframework.web.client.DefaultRestClient.readWithMessageConverters(DefaultRestClient.java:215) ~[spring-web-6.2.0.jar:6.2.0]
    at org.springframework.web.client.DefaultRestClient$DefaultResponseSpec.readBody(DefaultRestClient.java:811) ~[spring-web-6.2.0.jar:6.2.0]
    at org.springframework.web.client.DefaultRestClient$DefaultResponseSpec.lambda$body$0(DefaultRestClient.java:742) ~[spring-web-6.2.0.jar:6.2.0]
    at org.springframework.web.client.DefaultRestClient$DefaultRequestBodyUriSpec.exchangeInternal(DefaultRestClient.java:571) ~[spring-web-6.2.0.jar:6.2.0]
    at org.springframework.web.client.DefaultRestClient$DefaultRequestBodyUriSpec.exchange(DefaultRestClient.java:532) ~[spring-web-6.2.0.jar:6.2.0]
    at org.springframework.web.client.RestClient$RequestHeadersSpec.exchange(RestClient.java:677) ~[spring-web-6.2.0.jar:6.2.0]
    at org.springframework.web.client.DefaultRestClient$DefaultResponseSpec.executeAndExtract(DefaultRestClient.java:806) ~[spring-web-6.2.0.jar:6.2.0]
    at org.springframework.web.client.DefaultRestClient$DefaultResponseSpec.body(DefaultRestClient.java:742) ~[spring-web-6.2.0.jar:6.2.0]
    at org.springframework.ai.ollama.api.OllamaApi.chat(OllamaApi.java:125) ~[spring-ai-ollama-1.0.0-M5.jar:1.0.0-M5]
    at org.springframework.ai.ollama.OllamaChatModel.lambda$internalCall$2(OllamaChatModel.java:202) ~[spring-ai-ollama-1.0.0-M5.jar:1.0.0-M5]
    at io.micrometer.observation.Observation.observe(Observation.java:565) ~[micrometer-observation-1.14.1.jar:1.14.1]
    at org.springframework.ai.ollama.OllamaChatModel.internalCall(OllamaChatModel.java:200) ~[spring-ai-ollama-1.0.0-M5.jar:1.0.0-M5]
    at org.springframework.ai.ollama.OllamaChatModel.call(OllamaChatModel.java:184) ~[spring-ai-ollama-1.0.0-M5.jar:1.0.0-M5]
    at com.alibaba.cloud.ai.example.chat.deepseek.controller.OllamaChatModelController.functionCall(OllamaChatModelController.java:108) ~[classes/:na]
    at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:103) ~[na:na]
    at java.base/java.lang.reflect.Method.invoke(Method.java:580) ~[na:na]

到官网发现Function Calling有指出The current version of the deepseek-chat model's Function Calling capabilitity is unstable, which may result in looped calls or empty responses. We are actively working on a fix, and it is expected to be resolved in the next version.

到r1的github也有相关的issue,Function calling #9指出As of now, DeepSeek R1 does not natively support function calling or structured outputs.The model is primarily optimized for reasoning-heavy tasks (e.g., math, code, and STEM) and follows a conversational format.

切换model

不过ollama上面有些model进行改造,比如MFDoom/deepseek-r1-tool-calling,修改spring.ai.ollama.chat.model为MFDoom/deepseek-r1-tool-calling:1.5b,重新跑一下,发现可以支持

**Step-by-Step Explanation:** 1. **Identify the Query**: The user's query is "今天天气怎么样" (today's weather). 2. **Determine the Required Parameters**: The tool expects a `query` parameter, which is a string. 3. **Generate Output Based on the Query**: Using the provided function (`demoFunction`), we can generate weather information based on the query. 4. **Construct the Output String**: Replace the placeholder with the user's specific query and format the output as required. **Final Output:** {"result":"今天深圳天气晴朗"} ```json {"result":"今天深圳天气晴朗"} ```

不过实际还是挺考验prompt的书写的,写不好会造成很多次function调用

小结

DeepSeek的r1模型目前不支持funcation call,r1虽然有三方改造支持了,但是效果还不是太好,还是等官方支持了再来试试。

doc

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 220,137评论 6 511
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,824评论 3 396
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 166,465评论 0 357
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 59,131评论 1 295
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 68,140评论 6 397
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,895评论 1 308
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,535评论 3 420
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,435评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,952评论 1 319
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 38,081评论 3 340
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,210评论 1 352
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,896评论 5 347
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,552评论 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 32,089评论 0 23
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,198评论 1 272
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,531评论 3 375
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 45,209评论 2 357

推荐阅读更多精彩内容