赞
踩
/\*\* \* 工具流式问答 \* @param sessionId 会话ID \* @param prompt 提示词 \* @param baseTools 工具 \* @return \*/ @Override public Flux<String> streamChatWithTools(String sessionId, String prompt, List<BaseTool> baseTools) { String class2Json = buildClass2Json(new BaseTool()); String finalPrompt = String.format("你是一个AI助手,我会给你一个工具对象集合,工具对象包括name(工具名)、description(工具描述)、params(工具参数)。" + "你可以结合工具对象,从用户的问句中提取到关键词,确定要实现用户的任务应该喧杂哪个工具对象。" + "用户的任务是:%S。" + "工具对象集合是:%s。" + "您的响应结果必须为JSON格式,并且不要返回任何不必要的解释,只提供遵循此格式的符合RFC8259的JSON响应。以下是输出必须遵守的JSON Schema实例:```%s```", prompt, JSON.toJSONString(baseTools), class2Json); String funcParams = chat(finalPrompt); funcParams = JSON.parseObject(funcParams, OpenAIChatResponse.class).getChoices().get(0).getMessage().getContent(); funcParams = funcParams.substring(funcParams.indexOf("{"), funcParams.lastIndexOf("}")+1); String toolResult = LoadFunctions.load(JSON.parseObject(funcParams, BaseTool.class)); LOG.info("工具调用结果为:"+toolResult); String promptFormat = String.format("基于以下内容:{%s}。请回答:{%s}", toolResult, prompt); Flux<String> stringFlux = streamChat(sessionId, promptFormat); return stringFlux; }
创建一个自定义工具类,所有的工具都在这里实现,我这里创建了三个工具(查询天气、返回一个UUID、查询手机号的归属地):
public class FunctionCaller { /\*\* \* 查询天气API \* \* @param params \* @return \*/ public String getWeather(Map<String,Object> params) { String cityName = params.get("cityName").toString(); if (cityName == null || cityName.isEmpty()) { throw new IllegalArgumentException("City name must not be null or empty"); } OkHttpClient client = new OkHttpClient.Builder() .connectTimeout(60, TimeUnit.SECONDS) .writeTimeout(60, TimeUnit.SECONDS) .readTimeout(60, TimeUnit.SECONDS) .build(); try { Map<String, String> headers = new HashMap<>(16); headers.put("Content-Type", "application/json"); Request.Builder builder = new Request.Builder() .url("https://wttr.in/" + cityName + "?format=j1"); builder.headers(Headers.of(headers)); builder.method("GET", null); Request request = builder.build(); Response response = client.newCall(request).execute(); if (response.isSuccessful()) { ResponseBody responseBody = response.body(); JSONObject jsonObject = JSONObject.parseObject(responseBody.string()); JSONObject weatherData = new JSONObject(); // Extract the desired weather data from the JSON response JSONArray currentCondition = jsonObject.getJSONArray("current\_condition"); JSONObject firstEntry = currentCondition.getJSONObject(0); weatherData.put("temp\_C", firstEntry.getString("temp\_C")); weatherData.put("FeelsLikeC", firstEntry.getString("FeelsLikeC")); weatherData.put("humidity", firstEntry.getString("humidity")); weatherData.put("weatherDesc", firstEntry.getString("weatherDesc")); weatherData.put("observation\_time", firstEntry.getString("observation\_time")); weatherData.put("cityName", params.get("cityName").toString()); return weatherData.toString(); } else { throw new HttpRuntimeException("Failed.接口访问失败"); } } catch (IOException e) { e.printStackTrace(); return "Error encountered while fetching weather data!"; } } /\*\* \* 随机获取一个uuid \* @return \*/ public String getUuid(Map<String,Object> params){ return UUID.randomUUID().toString(); } /\*\* \* 查询手机号的归属地 \* @param params \* @return \*/ public String getMobileAddress(Map<String,Object> params) { String mobileNum = params.get("mobileNum").toString(); try { OkHttpClient client = new OkHttpClient.Builder() .connectTimeout(60, TimeUnit.SECONDS) .writeTimeout(60, TimeUnit.SECONDS) .readTimeout(60, TimeUnit.SECONDS) .build(); MediaType mediaType = MediaType.parse("application/x-www-form-urlencoded"); RequestBody body = RequestBody.create(mediaType, "mobile="+mobileNum); Request request = new Request.Builder() .url("https://eolink.o.apispace.com/teladress/teladress") .method("POST",body) .addHeader("X-APISpace-Token","v1a524e7ctm4h87ilxxxxxxxxxxxxx") .addHeader("Content-Type","") .build(); Response response = client.newCall(request).execute(); if (response.isSuccessful()) { ResponseBody responseBody = response.body(); return responseBody.string(); } else { throw new HttpRuntimeException("Failed.接口访问失败"); } } catch (Exception e) { e.printStackTrace(); return "Error fetching mobile address: " + e.getMessage(); } } }
然后,采用反射的方式调用这些工具:
/\*\* \* 通过反射机制调用函数 \* @param methodName \* @param jsonNode \* @return \*/ public static Object reflect(String methodName, Map<String,String> jsonNode){ FunctionCaller functionCaller = new FunctionCaller(); Method method = ReflectUtil.getMethod(FunctionCaller.class, methodName, new Class[]{Map.class}); try { Object invoke = method.invoke(functionCaller, jsonNode); return invoke; } catch (IllegalAccessException e) { LOG.error("FunctionReflect reflect occur illegal access exception,method name = {},jsonNode = {}",methodName,jsonNode,e); throw new RuntimeException(e); } catch (InvocationTargetException e) { LOG.error("FunctionReflect reflect occur invocation target exception,method name = {},jsonNode = {}",methodName,jsonNode,e); throw new RuntimeException(e); } }
调用的时候,将所有的工具集合作为参数,传入OpenAIChat的streamChatWithTools方法:
public static void test2(){ BaseTool baseTool = new BaseTool(); baseTool.setName("getWeather"); Map<String,String> map = new HashMap<>(16); map.put("cityName","城市"); baseTool.setParams(map); baseTool.setDescription("查询天气工具"); BaseTool baseTool1 = new BaseTool(); baseTool1.setName("getUuid"); baseTool1.setDescription("获取UUID"); baseTool1.setParams(null); BaseTool baseTool2 = new BaseTool(); baseTool2.setName("getMobileAddress"); baseTool2.setDescription("查询手机号归属地"); Map<String,String> map2 = new HashMap<>(16); map2.put("mobileNum","手机号"); baseTool2.setParams(map2); List<BaseTool> baseTools = Arrays.asList(baseTool,baseTool1,baseTool2); OpenAIChat openAIChat = OpenAIChat.builder() .endpointUrl("http://127.0.0.1:11434/v1/chat/completions") .model("qwen:7b-chat-v1.5-q5\_K\_M") **自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。** **深知大多数Python工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!** **因此收集整理了一份《2024年Python开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。** ![img](https://img-blog.csdnimg.cn/img_convert/c96cee9779f539f0735d75d8be0e7845.png) ![img](https://img-blog.csdnimg.cn/img_convert/c004c6a3aaccb34050281544372a9165.png) ![img](https://img-blog.csdnimg.cn/img_convert/46506ae54be168b93cf63939786134ca.png) ![img](https://img-blog.csdnimg.cn/img_convert/252731a671c1fb70aad5355a2c5eeff0.png) ![img](https://img-blog.csdnimg.cn/img_convert/6c361282296f86381401c05e862fe4e9.png) ![img](https://img-blog.csdnimg.cn/img_convert/9f49b566129f47b8a67243c1008edf79.png) **既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上前端开发知识点,真正体系化!** **由于文件比较大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且后续会持续更新** **如果你觉得这些内容对你有帮助,可以扫码获取!!!(备注Python)** 7b8a67243c1008edf79.png) **既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上前端开发知识点,真正体系化!** **由于文件比较大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且后续会持续更新** **如果你觉得这些内容对你有帮助,可以扫码获取!!!(备注Python)** <img src="https://img-community.csdnimg.cn/images/fd6ebf0d450a4dbea7428752dc7ffd34.jpg" alt="img" style="zoom:50%;" />
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。