����λ�ã���ҳ > �����̳� > �̳� > ��Ƚ���Spring AI����������Ӧ���Ƶĺ����߼�

��Ƚ���Spring AI����������Ӧ���Ƶĺ����߼�

��Դ������������|��ʱ�䣺2024-10-10 10:18:36 |���Ķ���114��|�� ��ǩ�� a �߼� Ri ���� S in AI �� |����������

������ǰ��������½��л����϶�Spring Boot 3�汾���±仯������ȫ��Ļعˣ���ȷ���ڽ������о�Spring AIʱ�ܹ������κ�DZ�ڵ����⡣���죬�������ڿ���ֱ�ӽ������⣺Spring AI����η������󲢽���Ϣ���ظ��û��ġ� �ڽ������������У����ǽ�רע����һ���̣�����ʽ�ش�ͺ����ص�����

������ǰ��������½��л����϶�Spring Boot 3�汾���±仯������ȫ��Ļعˣ���ȷ���ڽ������о�Spring AIʱ�ܹ������κ�DZ�ڵ����⡣���죬�������ڿ���ֱ�ӽ������⣺Spring AI����η������󲢽���Ϣ���ظ��û��ġ�

�ڽ������������У����ǽ�רע����һ���̣�����ʽ�ش�ͺ����ص�������������ǿ������´εĽ�������ϸ̽�֡�

��ʼ����

���ȣ����ڻ�û����Ŀ��ͬѧ������ذ�װ�����POM�������ע�⣬JDK�İ汾Ҫ��Ϊ17����ˣ��������IDEA���������غ���������汾��


http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    4.0.0
    
        org.springframework.boot
        spring-boot-starter-parent
        3.3.1
         
    
    com.example
    demo
    0.0.1-SNAPSHOT
    demo
    Demo project for Spring Boot
    
    
        
    
    
        
    
    
        
        
        
        
    
    
        17

        1.0.0-M2
    
    

        
            org.springframework.boot
            spring-boot-starter-actuator
        

        
            org.springframework.boot
            spring-boot-starter-web
        
        
            org.springframework.ai
            spring-ai-openai-spring-boot-starter
        
        
            com.github.xiaoymin
            knife4j-openapi3-jakarta-spring-boot-starter
            4.1.0
        
        
            javax.servlet
            javax.servlet-api
            4.0.1
        
        
            org.projectlombok
            lombok
            true
        
        
            org.springframework.boot
            spring-boot-starter-test
            test
        
    
    
        
            

                org.springframework.ai
                spring-ai-bom
                ${spring-ai.version}
                pom
                import
            
        
    

    
        
            
                org.graalvm.buildtools
                native-maven-plugin
                
                    
                    ${project.artifactId}
                    
                    com.example.demo.DemoApplication
                    
                        --no-fallback
                    
                
                
                    
                        build-native
                        
                            compile-no-fork
                        
                        package
                    
                
            
            
                org.springframework.boot
                spring-boot-maven-plugin
                
                    
                        
                            org.projectlombok
                            lombok
                        
                    
                
            
        
    
    
        
            spring-milestones
            Spring Milestones
            https://repo.spring.io/milestone
            
                false
            
        
    


�����÷���֮ǰ�Ľ������Ѿ����ǹ����������Ͳ�����ϸ˵����Ϊ�˸��õ�������һ������ǽ�ͨ�����������������������ʾ��

��һ�����ӽ�չʾ�����ش��ʵ�֣����ڶ�����������漰������������Ϣ����Ļش������ַ�ʽ���������Ǹ�������˽������ʵ��Ӧ�������������Щ������

�����÷�

���ォ�ṩһ�������ش���÷�ʾ�����Ա���õ�������Ӧ�ó����;���ʵ�ַ�ʽ��

@PostMapping("/ai")
ChatDataPO generationByText(@RequestParam("userInput")  String userInput) {
    String content = this.myChatClientWithSystem.prompt()
                .user(userInput)
                .call()
                .content();
    log.info("content: {}", content);
    ChatDataPO chatDataPO = ChatDataPO.builder().code("text").data(ChildData.builder().text(content).build()).build();;
    return chatDataPO;
}

�����ʾ���У����ǽ�չʾ���ʵ��һ���ȴ� AI ��ɻش�Ļ��ƣ��������ֱ�ӷ��ظ��ӿڵ��öˡ���һ����ʵ���Ϸdz��򵥣���ֻ�轫���⴫�ݸ� user �������ɡ������������ǽ�����Դ�������

Ϊ�˽�ʡʱ�䣬���Dz�����ϸ���з����м���̵Ĵ��룬��Ϊ����ܻ��Ե��߳������ӡ��෴�����ǽ�ֱ�Ӿ۽��ڹؼ�Դ�룬�Ա����Ч������������߼���ʵ��ϸ�ڡ�

Դ�����������������

��������ֱ�ӽ��� content �������������������ǰ��IJ����У����з����IJ���������Ҫ��Ϊ�˹���һ������Ϊ�����IJ�����׼�����������ĺ��ĵ����߼������� content �����ڲ���

private ChatResponse doGetChatResponse(DefaultChatClientRequestSpec inputRequest, String formatParam) {

            Map context = new ConcurrentHashMap<>();
            context.putAll(inputRequest.getAdvisorParams());
            DefaultChatClientRequestSpec advisedRequest = DefaultChatClientRequestSpec.adviseOnRequest(inputRequest,
                    context);

            var processedUserText = StringUtils.hasText(formatParam)
                    ? advisedRequest.getUserText() + System.lineSeparator() + "{spring_ai_soc_format}"
                    : advisedRequest.getUserText();

            Map userParams = new HashMap<>(advisedRequest.getUserParams());
            if (StringUtils.hasText(formatParam)) {
                userParams.put("spring_ai_soc_format", formatParam);
            }

            var messages = new ArrayList(advisedRequest.getMessages());
            var textsAreValid = (StringUtils.hasText(processedUserText)
                    || StringUtils.hasText(advisedRequest.getSystemText()));
            if (textsAreValid) {
                if (StringUtils.hasText(advisedRequest.getSystemText())
                        || !advisedRequest.getSystemParams().isEmpty()) {
                    var systemMessage = new SystemMessage(
                            new PromptTemplate(advisedRequest.getSystemText(), advisedRequest.getSystemParams())
                                .render());
                    messages.add(systemMessage);
                }
                UserMessage userMessage = null;
                if (!CollectionUtils.isEmpty(userParams)) {
                    userMessage = new UserMessage(new PromptTemplate(processedUserText, userParams).render(),
                            advisedRequest.getMedia());
                }
                else {
                    userMessage = new UserMessage(processedUserText, advisedRequest.getMedia());
                }
                messages.add(userMessage);
            }

            if (advisedRequest.getChatOptions() instanceof FunctionCallingOptions functionCallingOptions) {
                if (!advisedRequest.getFunctionNames().isEmpty()) {
                    functionCallingOptions.setFunctions(new HashSet<>(advisedRequest.getFunctionNames()));
                }
                if (!advisedRequest.getFunctionCallbacks().isEmpty()) {
                    functionCallingOptions.setFunctionCallbacks(advisedRequest.getFunctionCallbacks());
                }
            }
            var prompt = new Prompt(messages, advisedRequest.getChatOptions());
            var chatResponse = this.chatModel.call(prompt);

            ChatResponse advisedResponse = chatResponse;
            // apply the advisors on response
            if (!CollectionUtils.isEmpty(inputRequest.getAdvisors())) {
                var currentAdvisors = new ArrayList<>(inputRequest.getAdvisors());
                for (RequestResponseAdvisor advisor : currentAdvisors) {
                    advisedResponse = advisor.adviseResponse(advisedResponse, context);
                }
            }

            return advisedResponse;
        }

��δ���û���κ�ע�ͣ�ȷʵ���˸е����⣬���˵����Spring�������Ƴ��ԡ���������Ϊ���������ã�����Ϊ�����Ķ��������˼���ǣ��ܹ���Чʹ�þ��㹻�ˡ�������δ����Եü�����ˣ�������Ҫ�Բ��ݺ��ӡ����е�ʵ�ֶ��dz�������û������Ĵ��룬����Ҿ���������ɾ�������ǽ����������ֳ�����

Ϊ�˰�����Ҹ��õ��������е��߼��ͽṹ���ҽ�ʹ��α���������н��⡣

��ʼ�������� ������һ���յ������ġ�

������� ������������߼��ǻ��������Ķ�����������ж�̬���������ȣ�������Ҫ�ж���������Ƿ��Ѿ��� advisor ��װ�������Ҫ��ô���ǽ�����һ������ advisor ��װ����������

��������ص�Դ��ʵ�֣�չʾ����һ�߼��ľ���ϸ�ڣ�

public static DefaultChatClientRequestSpec adviseOnRequest(DefaultChatClientRequestSpec inputRequest,
                Map context) {

//....�˴�ʡ��һ�Ѵ���
        var currentAdvisors = new ArrayList<>(inputRequest.advisors);
                for (RequestResponseAdvisor advisor : currentAdvisors) {
                    adviseRequest = advisor.adviseRequest(adviseRequest, context);
                }
                advisedRequest = new DefaultChatClientRequestSpec(adviseRequest.chatModel(), adviseRequest.userText(),
                        adviseRequest.userParams(), adviseRequest.systemText(), adviseRequest.systemParams(),
                        adviseRequest.functionCallbacks(), adviseRequest.messages(), adviseRequest.functionNames(),
                        adviseRequest.media(), adviseRequest.chatOptions(), adviseRequest.advisors(),
                        adviseRequest.advisorParams(), inputRequest.getObservationRegistry(),
                        inputRequest.getCustomObservationConvention());
            }

            return advisedRequest;
        }

�����������ϸ����һ�� advisor.adviseRequest(adviseRequest, context) ��һ�����Ĺ��ܺ���Ҫ�ԡ����������Ѿ���������ǿ�࣬����������һ��������书�ܣ��÷��������þ��Ե���Ϊ�ؼ���������˵��������Դ�������������ǿ�������������ض���ҵ������

ֵ��ע����ǣ������ǿ����ķ���������ǿ��Ӧ�������Ӧ�ģ�����ͨ���ɶԳ��֡�������������鿴 adviseRequest �����ľ���ʵ�֣�

String content = this.myChatClientWithSystem.prompt()
                .advisors(new MessageChatMemoryAdvisor(chatMemory))
                .user(userInput)
                .call()
                .content();

���������� MessageChatMemoryAdvisor �࣬����ķ����ľ���ʵ���ǣ��ڽ��յ���Ӧ����Ϣ�󣬽�����Ϣ�洢��һ����������С�����һ������һ�δ�������ʱ���Ϳ���ֱ�Ӵ������������ȡ������ݡ�

public AdvisedRequest adviseRequest(AdvisedRequest request, Map context) {

    //�˴�ʡ��һ�Ѵ���
    // 4. Add the new user input to the conversation memory.
    UserMessage userMessage = new UserMessage(request.userText(), request.media());
    this.getChatMemoryStore().add(this.doGetConversationId(context), userMessage);

    return advisedRequest;
}

�����û��ı��������û����� ����Ҫ���� formatParam ���������û���������д�����������ԣ�������費���漰�����û��ı��ĸ�ʽ��������Ҫ������Ӧ���û�������

�����������ǽ�չʾ�����ʵ��ʾ�����Ա��������������һ���̵IJ���ϸ�ڣ�

.user(u -> u.text("""
                Generate the filmography for a random actor.
                {format}
              """)
            .param("format", converter.getFormat()))

����Ĵ���λὫ {format} �滻Ϊʵ�ʵĸ�ʽ����Ϣ�������û��ṩ�IJ����⣬ϵͳ��Ϣ��ͬ��������һЩ��Ҫ�����IJ�������Щ����Ҳ�����ڴ�����������ȷ�ش��롣

������Ϣ�б� ������ϵͳ�ı����û��ı�����Ч�ԣ�������Ϣ�Ĺ��̽����߽������ϡ����ǿ��Խ�������Ч����Ϣ���ӵ�һ�� List �����У��Ա��ں������������⣬ϵͳ���ᴴ��һ����Ϣ�������ڱ�����Щ��Ϣ�������Ϣ����ȷ������Ҫʱ���Է���ط��ʺ͹������ǡ�

�Ƿ��к����ص� ������У�������һ�¾���ĺ���������һ�½�ϸ����

����������ʾ ������һ����ʾnew Prompt()���󲢵�������ģ��api��ȡ������Ϣ��

������ǿ �������ǰ������������� advisor����ô���������Ӧ����ǿ���������⣬ϵͳ���Զ�����Ӧ���ʴ����ݴ洢����Ϣ�б��У������Ӧ����ϢҲ��Ҫ��һ����¼������

public ChatResponse adviseResponse(ChatResponse chatResponse, Map context) {

    List assistantMessages = chatResponse.getResults().stream().map(g -> (Message) g.getOutput()).toList();

    this.getChatMemoryStore().add(this.doGetConversationId(context), assistantMessages);

    return chatResponse;
}

���ؽ�� ���������յ�������Ӧ��

Դ�������������OpenAI

�����������ǽ���ϸ̽�����ͨ��������������� OpenAI �ӿڵľ�����̡�Ϊ�ˣ����ǽ��� OpenAI ��Դ��Ϊ�������з����������ʹ�õ������� AI ��Ʒ����ô����һ���ڵ����̽���������ͬ��ϵͳ����ݾ���IJ�Ʒ������Ӧ����ת����ͼ��ʾ��

Éî¶È½âÎöSpring AI£ºÇëÇóÓëÏìÓ¦»úÖÆµÄºËÐÄÂß¼­

���ǽ��� OpenAI ��������ù��̽���ȫ��Ľ����������������䱳��Ļ��ƺ�ʵ��ϸ�ڣ�

public ChatResponse call(Prompt prompt) {

    ChatCompletionRequest request = createRequest(prompt, false);

    ChatModelObservationContext observationContext = ChatModelObservationContext.builder()
        .prompt(prompt)
        .provider(OpenAiApiConstants.PROVIDER_NAME)
        .requestOptions(buildRequestOptions(request))
        .build();

    ChatResponse response = ChatModelObservationDocumentation.CHAT_MODEL_OPERATION
        .observation(this.observationConvention, DEFAULT_OBSERVATION_CONVENTION, () -> observationContext,
                this.observationRegistry)
        .observe(() -> {

            ResponseEntity completionEntity = this.retryTemplate
                .execute(ctx -> this.openAiApi.chatCompletionEntity(request, getAdditionalHttpHeaders(prompt)));

            var chatCompletion = completionEntity.getBody();

            if (chatCompletion == null) {
                logger.warn("No chat completion returned for prompt: {}", prompt);
                return new ChatResponse(List.of());
            }

            List choices = chatCompletion.choices();
            if (choices == null) {
                logger.warn("No choices returned for prompt: {}", prompt);
                return new ChatResponse(List.of());
            }

            List generations = choices.stream().map(choice -> {
        // @formatter:off
                Map metadata = Map.of(
                        "id", chatCompletion.id() != null ? chatCompletion.id() : "",
                        "role", choice.message().role() != null ? choice.message().role().name() : "",
                        "index", choice.index(),
                        "finishReason", choice.finishReason() != null ? choice.finishReason().name() : "",
                        "refusal", StringUtils.hasText(choice.message().refusal()) ? choice.message().refusal() : "");
                // @formatter:on
                return buildGeneration(choice, metadata);
            }).toList();

            // Non function calling.
            RateLimit rateLimit = OpenAiResponseHeaderExtractor.extractAiResponseHeaders(completionEntity);

            ChatResponse chatResponse = new ChatResponse(generations, from(completionEntity.getBody(), rateLimit));

            observationContext.setResponse(chatResponse);

            return chatResponse;

        });

    if (response != null && isToolCall(response, Set.of(OpenAiApi.ChatCompletionFinishReason.TOOL_CALLS.name(),
            OpenAiApi.ChatCompletionFinishReason.STOP.name()))) {
        var toolCallConversation = handleToolCalls(prompt, response);
        // Recursively call the call method with the tool call message
        // conversation that contains the call responses.
        return this.call(new Prompt(toolCallConversation, prompt.getOptions()));
    }

    return response;
}

��Ȼ��Щ���ݶ����м�ֵ��ɾ��������һ���õ�ѡ�񣬵�����ȱ��ע�ͣ����ǿ�����Ҫ��ϸ������������һ����������Щ��Ϣ�����������е��߼���Ҫ�㡣

createRequest ��������Ҫ�����ǹ�����ʵ�ʵ��� API ʱ���������������ڲ�ͬ�����ṩ�̵Ľӿ���Ƹ����ص㣬���������Ҫ���ݾ���� API �淶����ʵ����һ���̡����磬�ڵ��� OpenAI �Ľӿ�ʱ��������Ҫ�����ض��IJ����ṹ����һ���̴��Ӧ���Ѿ��dz���Ϥ������ͼ��ʾ�����ǿ��Կ�����������ʱ����ĸ�����������ʽ��

Éî¶È½âÎöSpring AI£ºÇëÇóÓëÏìÓ¦»úÖÆµÄºËÐÄÂß¼­

ChatModelObservationContext ��Ҫ����������������ص��������ƺ�Ҫ�����������ؼ����������籾���������� token �������ơ���ʹ�õ� OpenAI �ʴ�ģ�͵ľ������͡��Լ������Ƶ�����Ƶȡ��������ʾ��

private ChatOptions buildRequestOptions(OpenAiApi.ChatCompletionRequest request) {
    return ChatOptionsBuilder.builder()
        .withModel(request.model())
        .withFrequencyPenalty(request.frequencyPenalty())
        .withMaxTokens(request.maxTokens())
        .withPresencePenalty(request.presencePenalty())
        .withStopSequences(request.stop())
        .withTemperature(request.temperature())
        .withTopP(request.topP())
        .build();
}

ʣ�µ� ChatResponse �󷽷�����ʵ��ִ�� API ���󲢴�����Ӧ������һ�����У��м����ؼ�ϸ��ֵ��ע�⡣

�������ʹ�õ��� retryTemplate ������һ���������Ի��Ƶ����� API ���ߡ��������ּ����ǿ����Ŀɿ��ԣ��ر����������ʱ�Թ��ϻ���������ʱ���ܹ��Զ��������ԣ��Ӷ���߳ɹ��ʡ���Ϊ�����ǣ� retryTemplate �����û��������ã������㲻ͬӦ�ó���������

�û����Ը���ʵ����Ҫ�������Դ��������Լ��ʱ���Լ�������ز�����������Щ���ö�����ͨ�� spring.ai.retry ��һǰ׺�����Զ������á������ҿ��Կ�����ࣺ

@AutoConfiguration
@ConditionalOnClass(RetryTemplate.class)
@EnableConfigurationProperties({ SpringAiRetryProperties.class })
public class SpringAiRetryAutoConfiguration {
  //�˴�ʡ��һ�Ѵ���
}

���ţ���� OpenAI �Ľӿ�����������Ӧ����ôϵͳ����ʼ��ʽ���ش�����һ�����У��漰������ؼ��ֶΣ���Щ�ֶζ��ڳ���Ա�Ƕ���Ӧ�ö����൱��Ϥ�ģ���������Щ�й��ӿڶԽӾ���Ŀ����ߡ�

Map metadata = Map.of(
                            "id", chatCompletion.id() != null ? chatCompletion.id() : "",
                            "role", choice.message().role() != null ? choice.message().role().name() : "",
                            "index", choice.index(),
                            "finishReason", choice.finishReason() != null ? choice.finishReason().name() : "",
                            "refusal", StringUtils.hasText(choice.message().refusal()) ? choice.message().refusal() : "");

���ţ��ڽ��յ����з��ز�����ϵͳ����Щ�������ϲ����ظ� response ����Ȼ��������һ�׶Σ������ֽ�����һ����Ҫ���жϣ�����Ƿ�Ϊ isToolCall ������ж�ʵ�����漰�������ص��Ļ��ƣ���һ���ֵ�ʵ���߼��dz��ؼ������������ǾͲ�����̽�����ϸ�ڣ������´��ٽ��н��⡣

���ˣ��������������Ѿ�Բ����ɡ����ǵĽӿ�˳�������ؽ����������Ϣ���ظ��˵��öˣ�ȷ�����û�����ĸ�Ч��Ӧ��

�ܽ�

�����̽���У����Ǿ۽���Spring AI�����Ч�ط������󲢽���Ӧ��Ϣ���ݸ��û�����һ���̲����ǿ�������AI�����������������Ż��û�����Ĺؼ���ͨ����ȷ������ṹ����Ӧ���ƣ�Spring AI�ܹ����ش��������û����룬�����������ĵ����ش���ԡ�

Ȼ�����������������һ���Ƶĺ��ģ���ע����ʵ����ҵ���߼����ڴ˹����У�����ͨ��ʵ����ʾ�����ش���������ļ���Ļش������ʵ��Ӧ���з������á�������ʵ�ٲ����ܰ������Ǹ��õ�����Spring AI�Ĺ���ԭ����ҲΪ��������̽����ʽ�ش�ͺ����ص������˷��ʡ�

������һ���̵ı����߼�����Ϊ�������ճ�������Ӧ��Spring AI�ṩ����֧�֡����ż����IJ��Ͻ����������������ٵ���սҲ���������ӣ���ͨ��������������������Ӧ�ܹ������ǿ��Ը����ݵ�Ӧ�Ը����ԣ�ʵ�ָ������ܻ��Ľ��������


����Ŭ����С�꣬һ�� Java �������ũ��DZ���о��� AI �����İ��ء����Ȱ�����������������Կ�Դ�����������顣ͬʱҲ��һλ��Ѷ�ƴ���֮�ǡ�������ר�Ҳ�������Ϊ������ר�ҡ�����������ߡ�

? �ҽ����߷������ڼ�����·�ϵĸ���̽���뾭�飬ϣ����Ϊ���ѧϰ��ɳ�����һЩ�����������

? ��ӭ��עŬ����С�꣡?

С���Ƽ��Ķ�

�������������Ľ�Ϊ������Ϣ����������������ͬ���޹۵��֤ʵ��������

a 1.0
a 1.0
���ͣ���������������Ӫ״̬����ʽ��Ӫ�������ԣ����� ����

��Ϸ����

��Ϸ���

��Ϸ��Ƶ

��Ϸ����

��Ϸ�

��alittletotheleft������������һ��ܻ�ӭ����������������Ϸ����ҵ������Ƕ��ճ������еĸ���������
RPG RiÐòÕÂ 0.2.1
RPG Ri���� 0.2.1
���ͣ���ɫ����������Ӫ״̬����ʽ��Ӫ�������ԣ� ���ġ���

��Ϸ����

��Ϸ���

��Ϸ��Ƶ

��Ϸ����

��Ϸ�

��RPG_Ri���¡���GameMaker'Child-Dream'������һ����������RPG���Σ���ȫ��ѵĻ��������RPG�dz���Ԫ

�����Ƶ����

����

ͬ������

����

ɨ��ά�����������ֻ��汾��

ɨ��ά����������΢�Ź��ںţ�

��վ�������������������ϴ��������ַ���İ�Ȩ���뷢�ʼ�[email protected]

��ICP��2022002427��-10 �湫��������43070202000427��© 2013~2025 haote.com ������