1 @SpringBootApplication
2 public class _9a_HumanInTheLoop_Simple_Validator {
3
4 public static void main(String[] args) throws IOException {
5 ConfigurableApplicationContext context = SpringApplication.run(AgentDesignPatternApplication.class, args);
6 ChatModel model = context.getBean("ollamaChatModel", ChatModel.class);
7 RagProvider ragProvider = context.getBean("ragProvider", RagProvider.class);
8
9 // 3. 创建相关智能体
10 InterviewOrganizer interviewOrganizer = AgenticServices.agentBuilder(InterviewOrganizer.class)
11 .chatModel(model)
12 .tools(new OrganizingTools())
13 .contentRetriever(ragProvider.loadHouseRulesRetriever())
14 .build();
15
16 EmailAssistant emailAssistant = AgenticServices.agentBuilder(EmailAssistant.class)
17 .chatModel(model)
18 .tools(new OrganizingTools())
19 .build();
20
21 HiringDecisionProposer decisionProposer = AgenticServices.agentBuilder(HiringDecisionProposer.class)
22 .chatModel(model)
23 .outputKey("modelDecision")
24 .build();
25
26 // 2. 定义人工验证环节
27 HumanInTheLoop humanValidator = AgenticServices.humanInTheLoopBuilder()
28 .description("验证模型提出的招聘决策")
29 .inputKey("modelDecision")
30 .outputKey("finalDecision") // 由人工检查
31 .requestWriter(request -> {
32 System.out.println("AI招聘助手建议: " + request);
33 System.out.println("请确认最终决定。");
34 System.out.println("选项: 邀请现场面试 (I), 拒绝 (R), 暂缓 (H)");
35 System.out.print("> "); // 在实际系统中需要输入验证和错误处理
36 })
37 .responseReader(() -> new Scanner(System.in).nextLine())
38 .build();
39
40 // 3. 将智能体链接成工作流
41 UntypedAgent hiringDecisionWorkflow = AgenticServices.sequenceBuilder()
42 .subAgents(decisionProposer, humanValidator)
43 .outputKey("finalDecision")
44 .build();
45
46 // 4. 准备输入参数
47 Map<String, Object> input = Map.of(
48 "cvReview", new CvReview(0.85,
49 """
50 技术能力强,但缺乏所需的React经验。
51 似乎是快速独立学习者。文化契合度良好。
52 工作许可可能存在潜在问题,但似乎可以解决。
53 薪资期望略高于计划预算。
54 决定继续进行现场面试。
55 """)
56 );
57
58 System.out.println(input + "\n");
59
60 // 5. 运行工作流
61 String finalDecision = (String) hiringDecisionWorkflow.invoke(input);
62
63 System.out.println("\n=== 人工最终决定 ===");
64 System.out.println("(邀请现场面试 (I), 拒绝 (R), 暂缓 (H))\n");
65 System.out.println(finalDecision);
66
67 UntypedAgent candidateResponder = AgenticServices
68 .conditionalBuilder()
69 .subAgents(agenticScope -> finalDecision.contains("I"), interviewOrganizer)
70 .subAgents(agenticScope -> finalDecision.contains("R"), emailAssistant)
71 .subAgents(agenticScope -> finalDecision.contains("H"), new HoldOnAssist())
72 .build();
73
74 String candidateContact = StringLoader.loadFromResource("/documents/candidate_contact.txt");
75 String jobDescription = StringLoader.loadFromResource("/documents/job_description_backend.txt");
76
77
78 Map<String, Object> arguments = Map.of(
79 "candidateContact", candidateContact,
80 "jobDescription", jobDescription
81 );
82
83 // 6. 根据人工最终决定,进行下一步操作
84 candidateResponder.invoke(arguments);
85
86 // 注意:人工参与和人工验证通常需要较长时间等待用户响应。
87 // 在这种情况下,建议使用异步智能体,这样它们不会阻塞工作流的其余部分,
88 // 这些部分可以在用户回答之前潜在执行。
89 }
90 }