class ChatGlmChatModel implements ChatLanguageModel {

    private final ChatGlmClient client;
    private final Double temperature;
    private final Double topP;
    private final Integer maxLength;
    private final Integer maxRetries;

    @Builder
    public ChatGlmChatModel(String baseUrl, Duration timeout,
                            Double temperature, Integer maxRetries,
                            Double topP, Integer maxLength) {
        this.client = new ChatGlmClient(baseUrl, timeout);
        this.temperature = getOrDefault(temperature, 0.7);
        this.maxRetries = getOrDefault(maxRetries, 3);
        this.topP = topP;
        this.maxLength = maxLength;
    }


    @Override
    public Response<AiMessage> generate(List<ChatMessage> messages) {<FILL_FUNCTION_BODY>}

    private List<List<String>> toHistory(List<ChatMessage> historyMessages) {
        // Order: User - AI - User - AI ...
        // so the length of historyMessages must be divisible by 2
        if (containsSystemMessage(historyMessages)) {
            throw new IllegalArgumentException("ChatGLM does not support system prompt");
        }

        if (historyMessages.size() % 2 != 0) {
            throw new IllegalArgumentException("History must be divisible by 2 because it's order User - AI - User - AI ...");
        }

        List<List<String>> history = new ArrayList<>();
        for (int i = 0; i < historyMessages.size() / 2; i++) {
            history.add(historyMessages.subList(i * 2, i * 2 + 2).stream()
                    .map(ChatMessage::text)
                    .collect(Collectors.toList()));
        }

        return history;
    }

    private boolean containsSystemMessage(List<ChatMessage> messages) {
        return messages.stream().anyMatch(message -> message.type() == ChatMessageType.SYSTEM);
    }

    public static ChatGlmChatModelBuilder builder() {
        for (ChatGlmChatModelBuilderFactory factory : loadFactories(ChatGlmChatModelBuilderFactory.class)) {
            return factory.get();
        }
        return new ChatGlmChatModelBuilder();
    }

    public static class ChatGlmChatModelBuilder {
        public ChatGlmChatModelBuilder() {
            // This is public so it can be extended
            // By default with Lombok it becomes package private
        }
    }
}

        // get last user message
        String prompt = messages.get(messages.size() - 1).text();
        List<List<String>> history = toHistory(messages.subList(0, messages.size() - 1));
        ChatCompletionRequest request = ChatCompletionRequest.builder()
                .prompt(prompt)
                .temperature(temperature)
                .topP(topP)
                .maxLength(maxLength)
                .history(history)
                .build();

        ChatCompletionResponse response = withRetry(() -> client.chatCompletion(request), maxRetries);

        return Response.from(AiMessage.from(response.getResponse()));
    
<no_super_class>