spring boot 以请求来调用Ollama大模型,不使用spring ai

lannoy / 2024-08-30 / 原文

  之前有一版使用spring ai的,但是其实Ollama有一套api可以直接调用。api地址是https://github.com/ollama/ollama/blob/main/docs/api.md

  我们聊天其实调用的就是这个(其余的我就不赘述了,大家自行研究)

    调用http请求这方面,大家可自行编写,请求的方式五花八门,网上的库和组件都比较完善了。我就简单的分享一个本人的。

   1、引用配置 (yam文件不变)

        <dependency>
            <groupId>com.squareup.okhttp3</groupId>
            <artifactId>okhttp</artifactId>
            <version>4.12.0</version>
        </dependency>
        <dependency>
            <groupId>org.json</groupId>
            <artifactId>json</artifactId>
            <version>20240303</version>
        </dependency>

   2、编写实体类

import lombok.Data;

@Data
public class Message {
    private String content;

    private String role;
}

  role偷懒没做枚举类,ollama有4种,大家自己查阅。我这就是简单的主体。

import lombok.Data;
import java.util.List;

@Data
public class ChatRequestParam {

    private String model;

    private Boolean Stream;

    private List<Message> messages;
}

  3、http请求类

import okhttp3.CookieJar;
import okhttp3.Call;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;
import okhttp3.MediaType;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;
import java.util.concurrent.TimeUnit;

public class HttpClient {

    private final Logger logger = LoggerFactory.getLogger(HttpClient.class);

    private OkHttpClient createClient() {
        return new OkHttpClient().newBuilder()
                .callTimeout(1, TimeUnit.MINUTES)
                .cookieJar(CookieJar.NO_COOKIES)
                .build();
    }

    public String post(String url, String json) {
        OkHttpClient client = createClient();
        Request request = new Request.Builder()
                .url(url)
                .post(RequestBody.create(json, MediaType.get("application/json")))
                .build();
        Call call = client.newCall(request);
        logger.info("开始请求了");
        try {
            Response response = call.execute();
            String result = response.body().string();
            logger.info("请求结束,请求结果:{}", result);
            return result;
        } catch (Exception e) {
            logger.error("sorry,异常了:{}", e.getMessage());
            throw new RuntimeException(e);
        }
    }

    public Response get(String url, String json) throws IOException {
        OkHttpClient client = createClient();
        Request request = new Request.Builder()
                .url(url)
                .get()
                .build();
        request.newBuilder().setBody$okhttp(RequestBody.create(json, MediaType.get("application/json")));
        Call call = client.newCall(request);
        return call.execute();
    }
}

  4、请求类

@RestController
public class AnotherChatController {

    @Value("${spring.ai.ollama.base-url}")
    private String url;

    @Value("${spring.ai.ollama.chat.options.model}")
    private String model;

    private static final String chatApi = "/api/chat";

    @GetMapping("/ai/chat")
    public String chat(@RequestParam(value = "message", defaultValue = "Tell me a joke") String message) throws IOException {
        HttpClient httpClient = new HttpClient();
        String response = httpClient.post(url + chatApi, buildMainContent(message));
        return response;
    }

    private String buildMainContent (String msg) {
        ChatRequestParam chatRequestParam = new ChatRequestParam();
        chatRequestParam.setModel(model);
        chatRequestParam.setStream(false);
        Message target = new Message();
        target.setContent(msg);
        target.setRole("user");
        chatRequestParam.setMessages(List.of(target));
        return new JSONObject(chatRequestParam).toString();
    }
}

  注意,结果里面的response.body().string() 只能调用一次,调用完就销毁了,所以我们得存起来,不能反复引用。至此,完毕!