Prompt Enginering(提示工程)先进技术

前沿
CoT(Chain-of-Thought)和 ReACT(Reasoning and Acting)是两种先进的 Prompt Engineering(提示工程) 技术,旨在提升大语言模型(LLM)的推理、规划和执行能力。

  1. CoT(Chain-of-Thought,思维链)
    核心思想:通过引导模型生成中间推理步骤(step-by-step reasoning),模拟人类的渐进式思考过程,从而解决复杂问题。

特点:
显式推理:要求模型“展示思考过程”,例如先分解问题,再逐步推导答案。
适用场景:数学题、逻辑推理、需要多步分析的任务(如“如果A比B高,B比C高,谁最矮?”)。
实现方式:在Prompt中加入类似 “Let’s think step by step” 的指令,或提供少量CoT示例(Few-shot CoT)。
优势:显著提升模型在复杂任务中的准确性(如GSM8K数学数据集上效果提升明显)。
局限性:仅生成文本推理,不涉及外部动作(如搜索、调用工具)

实例 数学问题

问题:小明有5个苹果,吃了2个,又买了3个,现在有多少个?
模型输出(CoT):
1. 初始有5个苹果。
2. 吃掉2个后剩余:5 - 2 = 3个。
3. 买了3个后总数:3 + 3 = 6个。
最终答案:6个苹果。
  1. ReACT(Reasoning + Acting,推理与行动)
    核心思想:结合模型的推理能力和外部行动能力(如调用API、搜索、执行代码),通过交互式决策解决动态问题。

特点:
推理与行动交替:模型先思考(Reason),再决定是否采取行动(Act),最后观察结果并迭代。
适用场景:需要实时信息的任务(如问答)、工具调用(如计算器、数据库查询)、多步骤规划(如订机票+酒店)。
实现方式:Prompt中明确模板(如“Thought: … Action: … Observation: …”),并集成外部工具。
优势: 突破纯文本限制,通过工具扩展模型能力。
局限性: 依赖外部工具接口的设计和稳定性

示例(实时问答):

用户:2023年诺贝尔文学奖得主是谁?
模型输出(ReACT):
Thought: 我需要查找最新诺贝尔奖信息,应使用搜索工具。
Action: Search[2023 Nobel Literature Prize winner]
Observation: 2023年诺贝尔文学奖授予挪威作家Jon Fosse。
最终答案:Jon Fosse。

Java当中的实现

在Java中实现CoT(Chain-of-Thought)和ReACT(Reasoning and Acting)需要结合大语言模型(LLM)的API调用、动态Prompt生成以及外部工具集成。虽然Java生态的LLM工具链不如Python丰富,但通过HTTP客户端(如OkHttp)、JSON处理库(如Gson/Jackson)和规则引擎(如Drools)仍可构建完整流程。以下是具体实现方案:
1. 基础架构设计
在这里插入图片描述

2. 实现CoT(Chain-of-Thought)
方案1:静态模板(硬编码)

package com.prompt;import java.util.Map;
import java.util.HashMap;/*** 实现CoT(Chain-of-Thought) 静态模板*/
public class CotExample {public static String generateCotPrompt(String question) {// 定义CoT模板(可配置化)String template = """请逐步解决以下问题:问题:{question}步骤1:分析问题的关键点...步骤2:拆解子问题...步骤3:逐步计算...最终答案:""";// 变量替换Map<String, String> variables = new HashMap<>();variables.put("question", question);return replacePlaceholders(template, variables);}private static String replacePlaceholders(String template, Map<String, String> vars) {String result = template;for (Map.Entry<String, String> entry : vars.entrySet()) {result = result.replace("{" + entry.getKey() + "}", entry.getValue());}return result;}public static void main(String[] args) {String prompt = generateCotPrompt("小明有5个苹果,吃了2个,又买了3个,现在有多少个?");System.out.println(prompt);System.out.println(generateCotPrompt("鸡兔共有头10个,腿30个,求鸡和兔的数量?"));// 调用LLM API(见后续步骤)}
}

运行结果

步骤1:分析问题的关键点  
- 小明最开始有5个苹果。  
- 他吃掉了2个苹果。  
- 然后他又买了3个苹果。  
- 最后我们要计算他现在总共有多少个苹果。步骤2:拆解子问题  
- 小明吃掉了多少个苹果?  
- 吃掉苹果后还剩下多少个?  
- 买了多少个苹果?  
- 最后总共有多少个苹果?步骤3:逐步计算  
1. 小明最开始有5个苹果。
2. 吃掉2个苹果后:  5 - 2 = 3个苹果
3. 买了3个苹果后:  3 + 3 = 6个苹果最终答案:小明现在有6个苹果。

方案2:动态模板引擎(Apache Velocity)

<!-- pom.xml 依赖 -->
<dependency><groupId>org.apache.velocity</groupId><artifactId>velocity-engine-core</artifactId><version>2.4.1</version>
</dependency>
package com.prompt;import org.apache.velocity.VelocityContext;
import org.apache.velocity.app.Velocity;
import java.io.StringWriter;public class CotVelocity {public static String generateWithVelocity(String question) {Velocity.init();VelocityContext context = new VelocityContext();context.put("question", question);String template = """请逐步解决以下问题:#set($steps = ["分析问题的关键点", "拆解子问题", "逐步计算"])问题:$question#foreach($step in $steps)步骤${foreach.count}:$step...#end最终答案:""";StringWriter writer = new StringWriter();Velocity.evaluate(context, `writer`, "cot", template);return writer.toString();}public static void main(String[] args) {String promptStr =CotVelocity.generateWithVelocity("天上有多少颗星星");// 调用LLM API(见后续步骤)OpenAiChatModel model = OpenAiChatModel.builder().baseUrl("http://langchain4j.dev/demo/openai/v1").apiKey("demo").modelName(GPT_4_O_MINI)// .httpClientBuilder(new SpringRestClientBuilder()).logRequests(true).logResponses(true).build();System.out.println(model.generate(promptStr));}
}

运行结果

DEBUG: Request:
- method: POST
- url: http://langchain4j.dev/demo/openai/v1/chat/completions
- headers: [Authorization: Bearer ...], [User-Agent: langchain4j-openai]
- body: {"model" : "gpt-4o-mini","messages" : [ {"role" : "user","content" : "问题:天上有多少颗星星\n步骤1:分析问题的关键点...\n步骤2:拆解子问题...\n步骤3:逐步计算...\n最终答案:"} ],"temperature" : 0.7
}
2025-06-08 00:07:30 [main] dev.ai4j.openai4j.ResponseLoggingInterceptor.logDebug()
DEBUG: Response:
- status code: 200
- headers: [Date: Sat, 07 Jun 2025 16:07:22 GMT], [Content-Type: text/html;charset=utf-8], [Transfer-Encoding: chunked], [Server: Jetty(9.4.48.v20220622)]
- body: {"id":"chatcmpl-BfqMlXJE9BA8dVq2YpT04NHyHTNjV","created":1749312443,"model":"gpt-4o-mini-2024-07-18","choices":[{"index":0,"message":{"role":"assistant","content":"问题:天上有多少颗星星\n\n步骤1:分析问题的关键点\n- 这个问题实际上是一个开放性的问题,因为“星星”的定义和可见范围会影响答案。\n- 我们需要考虑可见星星的数量、银河系中的星星数量,以及宇宙中星星的总体估计。\n\n步骤2:拆解子问题\n1. 在晴朗的夜空中,肉眼可见的星星数量大约是多少?\n2. 银河系中大约有多少颗星星?\n3. 宇宙中大约有多少个银河系?每个银河系又大约有多少颗星星?\n\n步骤3:逐步计算\n1. 肉眼可见的星星数量:\n   - 在理想条件下,肉眼可见的星星大约在2000到3000颗之间。\n\n2. 银河系中的星星数量:\n   - 银河系中估计有1000亿到4000亿颗星星。我们可以取一个平均值,大约为2000亿颗。\n\n3. 宇宙中的银河系数量及其星星数量:\n   - 当前的研究表明,宇宙中大约有2000亿到3000亿个银河系。我们取一个中间值2500亿个银河系。\n   - 每个银河系平均约有2000亿颗星星。\n   - 因此,宇宙中的星星数量大约为:2500亿 × 2000亿 \u003d 5 × 10^22颗星星(即50000000000000000000000颗星星)。\n\n最终答案:\n在晴朗的夜空中,肉眼可见大约2000到3000颗星星;而在整个宇宙中,估计有大约50000000000000000000000颗星星。"},"finish_reason":"stop"}],"usage":{"prompt_tokens":44,"completion_tokens":403,"total_tokens":447},"system_fingerprint":"fp_34a54ae93c"}
问题:天上有多少颗星星步骤1:分析问题的关键点
- 这个问题实际上是一个开放性的问题,因为“星星”的定义和可见范围会影响答案。
- 我们需要考虑可见星星的数量、银河系中的星星数量,以及宇宙中星星的总体估计。步骤2:拆解子问题
1. 在晴朗的夜空中,肉眼可见的星星数量大约是多少?
2. 银河系中大约有多少颗星星?
3. 宇宙中大约有多少个银河系?每个银河系又大约有多少颗星星?步骤3:逐步计算
1. 肉眼可见的星星数量:- 在理想条件下,肉眼可见的星星大约在20003000颗之间。2. 银河系中的星星数量:- 银河系中估计有1000亿到4000亿颗星星。我们可以取一个平均值,大约为2000亿颗。3. 宇宙中的银河系数量及其星星数量:- 当前的研究表明,宇宙中大约有2000亿到3000亿个银河系。我们取一个中间值2500亿个银河系。- 每个银河系平均约有2000亿颗星星。- 因此,宇宙中的星星数量大约为:2500亿 × 2000亿 = 5 × 10^22颗星星(即50000000000000000000000颗星星)。最终答案:
在晴朗的夜空中,肉眼可见大约20003000颗星星;而在整个宇宙中,估计有大约50000000000000000000000颗星星。

3. 实现ReACT(Reasoning + Acting)

关键组件
LLM API调用:通过HTTP客户端访问OpenAI/Gemini等API。
动作调度器:根据LLM输出调用工具(如搜索、数据库)。
循环控制器:管理Thought→Action→Observation流程

案例一
模拟一个旅行规划AI Agent,需要协调航班查询、酒店预订和天气检查

1、首先定义一个工具类 模拟第三方接口的数据 (必须用 @Tool 注解)

package com.prompt.react;import dev.langchain4j.agent.tool.Tool;
import dev.langchain4j.agent.tool.ToolSpecification;
import dev.langchain4j.agent.tool.ToolSpecifications;
import dev.langchain4j.exception.IllegalConfigurationException;
import dev.langchain4j.service.AiServices;
import dev.langchain4j.service.tool.DefaultToolExecutor;import java.lang.reflect.Method;
import java.time.LocalDate;
import java.util.*;public class TravelTools {// 模拟航班数据库private static final Map<String, List<Flight>> FLIGHTS_DB = Map.of("NYC-LON", List.of(new Flight("DL123", "NYC", "LON", LocalDate.of(2023,12,25).plusDays(0), 599),new Flight("DL123", "NYC", "LON", LocalDate.of(2023,12,24).plusDays(1), 799),new Flight("BA456", "NYC", "LON", LocalDate.of(2023,12,24).plusDays(2), 699)),"纽约-伦敦", List.of(new Flight("DL128", "JFK", "LHR", LocalDate.of(2023,12,24).plusDays(1), 799),new Flight("BA459", "EWR", "LGW", LocalDate.of(2023,12,24).plusDays(2), 699)));// 模拟酒店数据库private static final Map<String, List<Hotel>> HOTELS_DB = Map.of("LON", List.of(new Hotel("Hilton", 250, 4.5),new Hotel("Premier Inn", 120, 4.0)),"London", List.of(new Hotel("Hilton", 250, 4.5),new Hotel("Premier Inn", 120, 4.0)));// 模拟天气APIprivate static final Map<String, String> WEATHER_DB = Map.of("LON-3days", "Sunny, 22°C / Rainy, 18°C / Cloudy, 20°C","London-3days", "Sunny, 22°C / Rainy, 18°C / Cloudy, 20°C");@Tool("查询航班信息 (参数示例: {'route':'NYC-LON','date':'2023-12-25'})")public String searchFlights(String departure,String destination, String date) {System.out.println("=================="+destination+"  "+date);return FLIGHTS_DB.getOrDefault(departure+"-"+destination, Collections.emptyList()).stream().filter(f -> f.date.equals(LocalDate.parse(date))).findFirst().map(f -> String.format("航班 %s: %s→%s, 价格 $%d",f.number, f.from, f.to, f.price)).orElse("无可用航班");}@Tool("查询酒店信息 (参数示例: {'city':'LON','budget':200})")public String searchHotels(String city, int budget) {System.out.println("----------------------酒店信息"+city);return HOTELS_DB.getOrDefault(city, Collections.emptyList()).stream().filter(h -> h.price <= budget).sorted(Comparator.comparingDouble(h -> -h.rating)).findFirst().map(h -> String.format("酒店 %s: $%d/晚, 评分 %.1f",h.name, h.price, h.rating)).orElse("无符合预算的酒店");}@Tool("查询目的地天气 (参数示例: {'city':'LON','days':3})")public String checkWeather(String city, int days) {System.out.println("--------------------------city weather: " + city);return WEATHER_DB.getOrDefault(city + "-" + days + "days", "天气数据暂不可用");}// 数据类record Flight(String number, String from, String to, LocalDate date, int price) {}record Hotel(String name, int price, double rating) {}public static List<ToolSpecification> tools(List<Object> objectsWithTools) {if(objectsWithTools==null) return Collections.emptyList();List<ToolSpecification> tools = new ArrayList<>();Iterator var2 = objectsWithTools.iterator();while(var2.hasNext()) {Object objectWithTool = var2.next();if (objectWithTool instanceof Class) {throw IllegalConfigurationException.illegalConfiguration("Tool '%s' must be an object, not a class", new Object[]{objectWithTool});}Method[] var4 = objectWithTool.getClass().getDeclaredMethods();int var5 = var4.length;for(int var6 = 0; var6 < var5; ++var6) {Method method = var4[var6];if (method.isAnnotationPresent(Tool.class)) {ToolSpecification toolSpecification = ToolSpecifications.toolSpecificationFrom(method);tools.add(toolSpecification);}}}return tools;}
}

2. ReACT Agent 实现(核心逻辑)

package com.prompt.react;import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import dev.langchain4j.agent.tool.*;
import dev.langchain4j.data.message.*;
import dev.langchain4j.memory.ChatMemory;
import dev.langchain4j.memory.chat.MessageWindowChatMemory;
import dev.langchain4j.model.openai.OpenAiChatModel;
import dev.langchain4j.model.output.Response;
import dev.langchain4j.service.tool.DefaultToolExecutor;
import dev.langchain4j.service.tool.ToolExecutor;import java.util.List;
import java.util.Map;
import java.util.UUID;import static dev.langchain4j.model.openai.OpenAiChatModelName.GPT_4_O_MINI;public class TravelPlanner {private final OpenAiChatModel model;private final ChatMemory memory;private final ToolExecutor toolExecutor;
String uuid = UUID.randomUUID().toString();public TravelPlanner(String apiKey) {
//        this.model = OpenAiChatModel.builder()
//                .baseUrl("http://langchain4j.dev/demo/openai/v1")
//                .apiKey("demo")
//                .modelName(GPT_4_O_MINI)
//                // .httpClientBuilder(new SpringRestClientBuilder())
//                .logRequests(true)
//                .logResponses(true)
//                .build();this.model = OpenAiChatModel.builder().apiKey(apiKey).baseUrl("https://api.deepseek.com/v1").modelName("deepseek-chat")//  .httpClientBuilder(new SpringRestClientBuilder()).strictTools(true) // https://docs.langchain4j.dev/integrations/language-models/open-ai#structured-outputs-for-tools.logRequests(true).logResponses(true).build();this.memory = MessageWindowChatMemory.withMaxMessages(20);this.toolExecutor = new ParallelToolExecutor(new TravelTools());// 关键:注入系统提示(强制ReACT格式)memory.add(SystemMessage.systemMessage("你是一个旅行规划AI,必须按以下步骤处理请求:\n" +"1. 分析用户需求\n" +"2. 调用工具获取数据\n" +"3. 综合结果给出建议\n\n" +"必须使用以下格式响应:\n" +"Thought: 思考过程\n" +"Action: 工具名\n" +"Action Input: {\"参数\":\"值\"}\n\n" +"可用工具:\n" +"- searchFlights (参数: departure, destination, date, maxBudget)\n" +"- searchHotels (参数: city, maxPrice)\n" +"- checkWeather (参数: city, days)"));}public String plan(String userRequest) throws InterruptedException {memory.add(UserMessage.userMessage(userRequest));System.out.println("=== 用户请求 ===\n" + userRequest);List<ToolSpecification> toolSpecifications = ToolSpecifications.toolSpecificationsFrom(TravelTools.class);for (int step = 1; step <= 5; step++) {// 1. 调用模型生成响应Response<AiMessage> response = model.generate(memory.messages(),toolSpecifications);AiMessage aiMessage = response.content();memory.add(aiMessage);// 2. 打印模型思考过程System.out.println("\n[Step " + step + "]");List<ToolExecutionRequest> toolExecutionRequests = aiMessage.toolExecutionRequests();// 3. 检查工具调用if (toolExecutionRequests ==null || toolExecutionRequests.isEmpty()) {return "\n=== 最终建议 ===\n" + aiMessage.text();}// 4. 执行所有工具调用toolExecutionRequests.forEach(req -> {String output = toolExecutor.execute(req,uuid);memory.add(ToolExecutionResultMessage.from(req, output));System.out.println("[工具执行] " + req.name() + " → " + output);});Thread.sleep(2000);}throw new RuntimeException("超过最大推理步数");}// 并行工具执行器static class ParallelToolExecutor implements ToolExecutor {private final TravelTools tools;ParallelToolExecutor(TravelTools tools) {this.tools = tools;}@Overridepublic String execute(ToolExecutionRequest request,Object o) {return switch (request.name()) {case "searchFlights" -> parseAndCall(request.arguments(),args -> tools.searchFlights(args.get("departure"),args.get("destination"), args.get("date")));case "searchHotels" -> parseAndCall(request.arguments(),args -> tools.searchHotels(args.get("city"), Integer.parseInt(args.get("budget"))));case "checkWeather" -> parseAndCall(request.arguments(),args -> tools.checkWeather(args.get("city"), Integer.parseInt(args.get("days"))));default -> throw new IllegalArgumentException("未知工具: " + request.name());};}private String parseAndCall(String jsonArgs, java.util.function.Function<Map<String, String>, String> func) {try {Map<String, String> args = new ObjectMapper().readValue(jsonArgs, new TypeReference<>() {});return func.apply(args);} catch (Exception e) {return "工具调用失败: " + e.getMessage();}}}
}

注意:不同大模型 返回的参数名略有差异 需要好好调试·
3. 主程序运行

package com.prompt.react;import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;public class TravelPlanningDemo {public static void main(String[] args) throws InterruptedException {String apiKey="sk-xx";TravelPlanner planner = new TravelPlanner(apiKey);String request = "帮我规划2023年12月25日从纽约到伦敦的旅行:" +"1. 查找预算$700以内的航班\n" +"2. 预订$200/晚以下的酒店\n" +"3. 检查3天内的天气";String result = planner.plan(request);System.out.println("\n=== 最终规划结果 ===");System.out.println(result);}
}

运行结果如下:

Connected to the target VM, address: '127.0.0.1:11304', transport: 'socket'
=== 用户请求 ===
帮我规划20231225日从纽约到伦敦的旅行:1. 查找预算$700以内的航班
2. 预订$200/晚以下的酒店
3. 检查3天内的天气[Step 1]
==================LON  2023-12-25
[工具执行] searchFlights → 航班 DL123: NYCLON, 价格 $599
----------------------酒店信息London
[工具执行] searchHotels → 酒店 Premier Inn: $120/, 评分 4.0
--------------------------city weather: London
[工具执行] checkWeather → Sunny, 22°C / Rainy, 18°C / Cloudy, 20°C[Step 2]=== 最终规划结果 ====== 最终建议 ===
Thought: 已获取航班、酒店和天气信息,现在综合结果给出建议。### 旅行规划建议:
1. **航班**- **航班号**DL123  - **路线**:纽约 (NYC) → 伦敦 (LON)  - **日期**20231225- **价格**:$599(在您的预算$700以内)  2. **酒店**- **名称**Premier Inn  - **价格**:$120/晚(在您的预算$200/晚以内)  - **评分**4.0  3. **天气**(伦敦未来3天):  - 第一天:晴天,22°C  - 第二天:雨天,18°C  - 第三天:多云,20°C  ### 下一步建议:
- 确认航班和酒店预订。  
- 根据天气情况准备衣物(建议带雨具)。  
- 如需进一步帮助,请告知!  Process finished with exit code 0

案例二
该案例模拟一个 金融投资顾问AI,需要协同调用股票查询、风险评估和投资组合优化工具

1、 复杂工具定义
模拟三个关键服务:股票数据、风险评估、组合优化

package com.prompt.invest;import dev.langchain4j.agent.tool.Tool;
import com.google.gson.Gson;public class InvestmentTools {private static final Gson gson = new Gson();public static void main(String[] args) {System.out.println(gson.fromJson("{\"request\": {\"symbol\": \"AAPL\", \"days\": 30}}".replace("{\"request\":","").replace("}","")+"}", StockRequest.class));}// 工具1:股票数据查询@Tool("查询股票实时数据 (参数示例: {'symbol':'AAPL','days':30})")public String getStockData(StockRequest request) {System.out.println("======================getStockData");return String.format("""%s股票最近%d天数据:- 当前价: $%.2f- 波动率: %.2f%%- 市盈率: %.1f""",request.symbol, request.days,Math.random() * 100 + 100, // 模拟价格Math.random() * 20 + 5,    // 模拟波动率Math.random() * 10 + 15     // 模拟PE);}// 工具2:风险评估@Tool("评估投资组合风险 (参数示例: {'stocks':['AAPL','MSFT'],'total_amount':10000})")public String assessRisk(PortfolioRequest request) {System.out.println("======================assessRisk");return String.format("""组合风险评估 (总金额: $%,d):- 最大回撤: %.1f%%- 夏普比率: %.2f- 风险等级: %s""",request.total_amount,Math.random() * 15 + 5,Math.random() * 2 + 0.5,new String[]{"A","B","C"}[(int)(Math.random()*3)]);}// 工具3:组合优化@Tool("生成优化投资组合 (参数示例: {'stocks':['AAPL','MSFT'],'risk_level':'B','amount':10000})")public String optimizePortfolio(OptimizationRequest request) {System.out.println("======================optimizePortfolio");return String.format("""优化建议 (风险等级 %s):- AAPL: %.0f%%- MSFT: %.0f%%- 现金: %.0f%%""",request.risk_level,(0.6 + Math.random() * 0.2) * 100,(0.3 + Math.random() * 0.1) * 100,Math.random() * 10);}// 参数类(强制JSON结构)public static class StockRequest {public String symbol;public int days;@Overridepublic String toString() {return "StockRequest{" +"symbol='" + symbol + '\'' +", days=" + days +'}';}public StockRequest() {}public StockRequest(String symbol, int days) {this.symbol = symbol;this.days = days;}public String getSymbol() {return symbol;}public void setSymbol(String symbol) {this.symbol = symbol;}public int getDays() {return days;}public void setDays(int days) {this.days = days;}}public static class PortfolioRequest {public String[] stocks;public int total_amount;public PortfolioRequest(String[] stocks, int total_amount) {this.stocks = stocks;this.total_amount = total_amount;}public PortfolioRequest() {}public String[] getStocks() {return stocks;}public void setStocks(String[] stocks) {this.stocks = stocks;}public int getTotal_amount() {return total_amount;}public void setTotal_amount(int total_amount) {this.total_amount = total_amount;}}public static class OptimizationRequest {public String[] stocks;public String risk_level;public int amount;public OptimizationRequest() {}public OptimizationRequest(String[] stocks, String risk_level, int amount) {this.stocks = stocks;this.risk_level = risk_level;this.amount = amount;}public String[] getStocks() {return stocks;}public void setStocks(String[] stocks) {this.stocks = stocks;}public int getAmount() {return amount;}public void setAmount(int amount) {this.amount = amount;}public String getRisk_level() {return risk_level;}public void setRisk_level(String risk_level) {this.risk_level = risk_level;}}
}

2. ReACT Agent核心实现
严格保证工具调用顺序和参数传递

package com.prompt.invest;import com.google.gson.Gson;
import com.prompt.react.TravelTools;
import dev.langchain4j.agent.tool.*;
import dev.langchain4j.data.message.*;
import dev.langchain4j.memory.ChatMemory;
import dev.langchain4j.memory.chat.MessageWindowChatMemory;
import dev.langchain4j.model.chat.ChatLanguageModel;
import dev.langchain4j.model.openai.OpenAiChatModel;
import dev.langchain4j.model.output.Response;
import dev.langchain4j.service.tool.ToolExecutor;import java.util.*;import static dev.langchain4j.model.openai.OpenAiChatModelName.GPT_4_O_MINI;public class InvestmentAdvisor {private final OpenAiChatModel model;private final ChatMemory memory;private final ToolExecutor toolExecutor;public InvestmentAdvisor(String apiKey) {this.model = OpenAiChatModel.builder().apiKey(apiKey).baseUrl("https://api.deepseek.com/v1").modelName("deepseek-chat")//  .httpClientBuilder(new SpringRestClientBuilder()).strictTools(true) // https://docs.langchain4j.dev/integrations/language-models/open-ai#structured-outputs-for-tools.logRequests(true).logResponses(true).build();this.memory = MessageWindowChatMemory.withMaxMessages(30);this.toolExecutor = new StrictToolExecutor(new InvestmentTools());// 注入强约束系统提示memory.add(SystemMessage.systemMessage("""你是一个高级投资顾问,必须按以下步骤操作:1. 先查询股票数据2. 然后评估当前组合风险3. 最后生成优化建议必须使用以下工具和格式:Action: 工具名Action Input: {"参数":"值"}"""));}public String advise(String request) {memory.add(UserMessage.userMessage(request));System.out.println("\n=== 开始处理 ===");System.out.println("[用户请求] " + request);List<ToolSpecification> toolSpecifications = ToolSpecifications.toolSpecificationsFrom(InvestmentTools.class);for (int i = 1; i <= 6; i++) {// 1. 生成响应Response<AiMessage> response = model.generate(memory.messages(),toolSpecifications);AiMessage aiMessage = response.content();memory.add(aiMessage);List<ToolExecutionRequest> toolExecutionRequests = aiMessage.toolExecutionRequests();// 2. 处理工具调用if (toolExecutionRequests!=null && !toolExecutionRequests.isEmpty()) {toolExecutionRequests.forEach(req -> {String output = toolExecutor.execute(req,null);memory.add(ToolExecutionResultMessage.from(req, output));logToolCall(req, output);});} else {if(aiMessage.text() ==null){continue;}return formatFinalAnswer(aiMessage.text());}if(aiMessage.text() ==null){continue;}logThought(aiMessage.text());}throw new RuntimeException("超过最大处理步数");}// 严格参数校验的执行器private static class StrictToolExecutor implements ToolExecutor {private final InvestmentTools tools;private final Gson gson = new Gson();StrictToolExecutor(InvestmentTools tools) {this.tools = tools;}@Overridepublic String execute(ToolExecutionRequest request,Object memoryId) {try {return switch (request.name()) {case "getStockData" ->tools.getStockData(gson.fromJson(request.arguments().replace("{\"request\":","").replace("}","")+"}", InvestmentTools.StockRequest.class));case "assessRisk" ->tools.assessRisk(gson.fromJson(request.arguments().replace("{\"request\":","").replace("}","")+"}", InvestmentTools.PortfolioRequest.class));case "optimizePortfolio" ->tools.optimizePortfolio(gson.fromJson(request.arguments().replace("{\"request\":","").replace("}","")+"}", InvestmentTools.OptimizationRequest.class));default -> throw new IllegalArgumentException("未知工具: " + request.name());};} catch (Exception e) {return "执行失败: " + e.getMessage();}}}private void logThought(String thought) {System.out.println("[AI思考] " + thought.split("\n")[0]); // 只打印第一行}private void logToolCall(ToolExecutionRequest req, String output) {System.out.printf("[Step %d] 调用工具: %s(%s)\n   结果: %s\n",memory.messages().size() / 2, // 粗略计算步数req.name(),req.arguments().replace(",", ",\n    "),output.replace("\n", "\n    "));}private String formatFinalAnswer(String text) {return "\n=== 最终建议 ===\n" + text;}
}

3、主程序测试

public static void main(String[] args) {String apiKey="sk-xx";InvestmentAdvisor advisor = new InvestmentAdvisor(apiKey);String result = advisor.advise("请分析AAPL和MSFT的投资组合,总金额50000美元,风险等级B");System.out.println(result);
}

运行结果如下:

=== 开始处理 ===
[用户请求] 请分析AAPLMSFT的投资组合,总金额50000美元,风险等级B
======================getStockData
[Step 2] 调用工具: getStockData({"request": {"symbol": "AAPL","days": 30}})结果: AAPL股票最近30天数据:- 当前价: $121.81- 波动率: 21.18%- 市盈率: 20.6
======================getStockData
[Step 2] 调用工具: getStockData({"request": {"symbol": "MSFT","days": 30}})结果: MSFT股票最近30天数据:- 当前价: $142.23- 波动率: 8.33%- 市盈率: 22.1
======================assessRisk
[Step 3] 调用工具: assessRisk({"request":{"stocks":["AAPL","MSFT"],"total_amount":50000}})结果: 组合风险评估 (总金额: $50,000):- 最大回撤: 5.5%- 夏普比率: 0.76- 风险等级: B
======================optimizePortfolio
[Step 4] 调用工具: optimizePortfolio({"request":{"stocks":["AAPL","MSFT"],"risk_level":"B","amount":50000}})结果: 优化建议 (风险等级 B):- AAPL: 68%- MSFT: 40%- 现金: 1%=== 最终建议 ===
### 分析结果#### 1. 股票数据查询
- **AAPL**:- 当前价: $121.81- 波动率: 21.18%- 市盈率: 20.6
- **MSFT**:- 当前价: $142.23- 波动率: 8.33%- 市盈率: 22.1#### 2. 组合风险评估
- **总金额**: $50,000
- **最大回撤**: 5.5%
- **夏普比率**: 0.76
- **风险等级**: B#### 3. 优化建议
根据风险等级 **B**,优化后的投资组合建议如下:
- **AAPL**: 68% (约 $34,000)
- **MSFT**: 40% (约 $20,000)
- **现金**: 1% (约 $500)### 说明
- **AAPL** 的波动率较高,适合在组合中承担更高的风险收益比。
- **MSFT** 的波动率较低,适合作为稳定收益的部分。
- 保留少量现金以应对市场波动。如果需要进一步调整或优化,请告知!

感谢 各位看官的支持 【zwpflc】
有问题可以给我留言 多交流

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.pswp.cn/bicheng/84165.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【C++系列】模板类型特例化

1. C模板类型特例化介绍 ​​定义​​&#xff1a;模板类型特例化&#xff08;Template Specialization&#xff09;是C中为模板的特定类型提供定制实现的机制&#xff0c;允许开发者对通用模板无法处理的特殊类型进行优化或特殊处理。 ​​产生标准​​&#xff1a; C98/03…

AI数据分析在体育中的应用:技术与实践

在现代体育竞技领域&#xff0c;"数据驱动"已不再是一个遥远的概念。尤其随着人工智能&#xff08;AI&#xff09;和大数据分析的不断成熟&#xff0c;从职业俱乐部到赛事直播平台&#xff0c;从运动员训练到球迷观赛体验&#xff0c;AI正以前所未有的方式渗透并改变…

计数思想-众数

11203-众数 题目描述(Description) 众数是指在一组数据中&#xff0c;出现次数最多的数。例如&#xff1a;1, 1, 3 中出现次数最多的数为 1&#xff0c;则众数为 1。 给定一组数&#xff0c;你能求出众数吗&#xff1f; 输入格式(Format Input) 第 1 行输入一个整数 n (1 &…

【Go语言基础【20】】Go的包与工程

文章目录 零、概述一、包基础1、包的核心作用2、包的声明与结构2.1、 包声明&#xff08;Package Declaration&#xff09;2.2、 包的目录结构&#xff08;工程视角&#xff09; 3、包的导入与调用3.1、导入包&#xff08;Import Packages&#xff09;3.2、 调用包成员3.3、 导…

《C++初阶之入门基础》【命名空间 + 输入输出 + 缺省参数 + 函数重载】

【命名空间 输入&输出 缺省参数 函数重载】目录 前言&#xff1a;---------------hello world---------------比较C语言和C的第一个程序&#xff1a;hello word ---------------命名空间---------------什么是命名空间&#xff1f;怎么使用命名空间&#xff1f;怎么定义…

java综合项目开发一课一得

文章目录 Java 综合项目课程学习&#xff1a;探索与成长之路一、课程初体验&#xff1a;从理论走向实践&#xff08;一&#xff09;系统学习 Java 核心理论知识&#xff08;二&#xff09;开启首个实践项目 —— 图书管理系统 二、项目攻坚&#xff1a;挑战与突破&#xff08;一…

JuiceFS v1.3-Beta2:集成 Apache Ranger,实现更精细化的权限控制

在大数据场景中&#xff0c;文件系统和应用组件的权限管理至关重要。在最新发布的 JuiceFS 社区版 v1.3-Beta 2 中&#xff0c;JuiceFS 引入了与 Apache Ranger 的集成&#xff0c;提供了更为灵活和细粒度的权限控制解决方案。 本文将介绍 JuiceFS 社区版如何与 Apache Ranger…

6月8日day48打卡

随机函数与广播机制 知识点回顾&#xff1a; 随机张量的生成&#xff1a;torch.randn函数卷积和池化的计算公式&#xff08;可以不掌握&#xff0c;会自动计算的&#xff09;pytorch的广播机制&#xff1a;加法和乘法的广播机制 ps&#xff1a;numpy运算也有类似的广播机制&…

计算机常用快捷键分类汇总,涵盖 Windows、macOS 以及通用软件场景

一、系统通用快捷键 功能Windows 快捷键macOS 快捷键复制Ctrl CCommand C粘贴Ctrl VCommand V剪切Ctrl XCommand X撤销Ctrl ZCommand Z全选Ctrl ACommand A保存Ctrl SCommand S打印Ctrl PCommand P新建窗口/标签页Ctrl NCommand N关闭当前窗口/标签页Ctrl WC…

ES6中的Map与Set数据结构的简单应用

一、Map定义和基本用法 Map是一种键值对集合&#xff0c;其中键和值都可以是任何类型&#xff08;对象、原始值等&#xff09;。与普通对象不同&#xff0c;Map保持键值对的插入顺序&#xff0c;并且允许使用任何类型的键。 1、创建Map const map new Map()2、添加键值对。…

25.【.NET8 实战--孢子记账--从单体到微服务--转向微服务】--单体转微服务--用户服务接口

用户管理是任何系统的基础功能之一&#xff0c;本篇介绍了如何实现一个完整的用户管理模块&#xff0c;包括用户信息的增删改查、用户状态管理、分页查询、数据验证和权限控制。核心代码实现部分涵盖了控制器&#xff08;UserController&#xff09;、服务接口&#xff08;IUse…

基于深度学习的无人机轨迹预测

完整代码见文末 随着无人机技术的不断发展,无人机在农业、物流、监控等领域的应用日益广泛。精准的轨迹预测不仅能够提高无人机飞行的效率和安全性,还能在应对复杂环境下的突发状况时做出迅速反应。因此,基于深度学习的无人机轨迹预测已成为当前研究和应用的热门方向。 无…

AUTOSAR实战教程--DoIP_02_诊断链路建立流程

第一步&#xff1a;DoIP实体车辆声明/诊断仪车辆识别请求 打开激活线以后&#xff0c;DoIP实体发的三帧车辆声明报文。其中包含了DoIP实体的诊断逻辑地址&#xff08;可以类比DoCAN的物理请求/响应地址&#xff09;&#xff0c;对应车辆的VIN码&#xff08;若已配置&#xff0…

跟我学c++中级篇——多线程中的文件处理

一、文件处理 作为IO处理的一种重要场景&#xff0c;文件处理是几乎所有编程都无法绕过的一个情况。稍微复杂的一些的程序都可能需要文件处理&#xff0c;不管这种文件处理对开发者来说是显式的还是隐式的。相对于其它语言&#xff0c;C并未提供多么好的文件处理API接口&#…

Flutter知识点汇总

Flutter架构解析 1. Flutter 是什么?它与其他移动开发框架有什么不同? Flutter 是 Google 开发的开源移动应用开发框架,可用于快速构建高性能、高保真的移动应用(iOS 和 Android),也支持 Web、桌面和嵌入式设备。。它与其他移动开发框架(如 React Native、Xamarin、原…

【会员专享数据】1980—2022年中国逐日月年潜在蒸散发栅格数据

气象数据是我们在各项研究中都经常使用的数据&#xff0c;尤其是高精度的气象数据应用价值非常高。 之前我们分享过研究者张凌, 胡英屹等发布在国家冰川冻土沙漠科学数据中心平台上的nc格式的1980—2022年中国高分辨率逐日、逐月、逐年气象数据&#xff01;很多小伙伴拿到数据…

前端打包工具简单介绍

前端打包工具简单介绍 一、Webpack 架构与插件机制 1. Webpack 架构核心组成 Entry&#xff08;入口&#xff09; 指定应用的起点文件&#xff0c;比如 src/index.js。 Module&#xff08;模块&#xff09; Webpack 把项目当作模块图&#xff0c;模块可以是 JS、CSS、图片等…

工业控制核心引擎高性能MCU——MM32F5370

RAMSUN提供的MM32F5370搭载180MHz Arm China Star-MC1处理器&#xff0c;集成DSP、FPU与三角函数加速单元&#xff08;CORDIC&#xff09;&#xff0c;轻松应对复杂算法需求。其技术亮点包括&#xff1a; 超高精度PWM&#xff1a;8通道208ps级高精度PWM输出&#xff0c;满足储能…

AI架构师修炼之道

1 AI时代的架构革命 与传统软件开发和软件架构师相比&#xff0c;AI架构师面临着三重范式转换&#xff1a; 1.1 技术维度&#xff0c;需处理异构算力调度与模型生命周期管理的复杂性&#xff1b; 1.2 系统维度&#xff0c;需平衡实时性与资源约束的矛盾&#xff1b; 1.3 价…

数学建模期末速成 主成分分析的基本步骤

设有 n n n个研究对象&#xff0c; m m m个指标变量 x 1 , x 2 , ⋯ , x m x_1,x_2,\cdots,x_m x1​,x2​,⋯,xm​&#xff0c;第 i i i个对象关于第 j j j个指标取值为 a i j a_{ij} aij​,构造数据矩阵 A ( a i j ) n m A\left(\begin{array}{c}a_{ij}\end{array}\right)_{…