(improvement)(common) Upgraded langchain4j to version 0.31. (#1174)

This commit is contained in:
lexluo09
2024-06-20 17:31:19 +08:00
committed by GitHub
parent 1df1fe5ad6
commit 92db381b6f
37 changed files with 241 additions and 888 deletions

View File

@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>supersonic</artifactId>
<groupId>com.tencent.supersonic</groupId>
@@ -23,7 +23,6 @@
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
@@ -155,10 +154,6 @@
</dependency>
<!--langchain4j-->
<dependency>
<groupId>dev.langchain4j</groupId>
<artifactId>langchain4j-spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>dev.langchain4j</groupId>
<artifactId>langchain4j-open-ai</artifactId>
@@ -183,7 +178,6 @@
<groupId>dev.langchain4j</groupId>
<artifactId>langchain4j-embeddings-bge-small-zh</artifactId>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-api</artifactId>
@@ -193,11 +187,45 @@
<groupId>dev.langchain4j</groupId>
<artifactId>langchain4j-embeddings</artifactId>
</dependency>
<dependency>
<groupId>dev.langchain4j</groupId>
<artifactId>langchain4j-spring-boot-starter</artifactId>
<version>${langchain4j.version}</version>
</dependency>
<dependency>
<groupId>dev.langchain4j</groupId>
<artifactId>langchain4j-anthropic-spring-boot-starter</artifactId>
<version>${langchain4j.version}</version>
</dependency>
<dependency>
<groupId>dev.langchain4j</groupId>
<artifactId>langchain4j-ollama-spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>dev.langchain4j</groupId>
<artifactId>langchain4j-open-ai-spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>dev.langchain4j</groupId>
<artifactId>langchain4j-azure-ai-search-spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>dev.langchain4j</groupId>
<artifactId>langchain4j-azure-open-ai-spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>dev.langchain4j</groupId>
<artifactId>langchain4j-embeddings-all-minilm-l6-v2-q</artifactId>
</dependency>
<dependency>
<groupId>com.hankcs</groupId>
<artifactId>hanlp</artifactId>
<version>${hanlp.version}</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
</dependency>
</dependencies>
</project>

View File

@@ -4,8 +4,9 @@ import com.tencent.supersonic.common.config.LLMConfig;
import com.tencent.supersonic.common.pojo.enums.S2ModelProvider;
import dev.langchain4j.model.chat.ChatLanguageModel;
import dev.langchain4j.model.localai.LocalAiChatModel;
import dev.langchain4j.model.openai.FullOpenAiChatModel;
import dev.langchain4j.model.openai.OpenAiChatModel;
import org.apache.commons.lang3.StringUtils;
import java.time.Duration;
public class S2ChatModelProvider {
@@ -17,7 +18,7 @@ public class S2ChatModelProvider {
return chatLanguageModel;
}
if (S2ModelProvider.OPEN_AI.name().equalsIgnoreCase(llmConfig.getProvider())) {
return FullOpenAiChatModel
return OpenAiChatModel
.builder()
.baseUrl(llmConfig.getBaseUrl())
.modelName(llmConfig.getModelName())

View File

@@ -1,30 +0,0 @@
package dev.langchain4j;
class InProcess {
/***
* the model local path
*/
private String modelPath;
/***
* the model's vocabulary local path
*/
private String vocabularyPath;
public String getModelPath() {
return modelPath;
}
public void setModelPath(String modelPath) {
this.modelPath = modelPath;
}
public String getVocabularyPath() {
return vocabularyPath;
}
public void setVocabularyPath(String vocabularyPath) {
this.vocabularyPath = vocabularyPath;
}
}

View File

@@ -1,59 +0,0 @@
package dev.langchain4j;
import com.tencent.supersonic.common.pojo.enums.S2ModelProvider;
import org.springframework.boot.context.properties.NestedConfigurationProperty;
class S2EmbeddingModel {
@NestedConfigurationProperty
private S2ModelProvider provider;
@NestedConfigurationProperty
private OpenAi openAi;
@NestedConfigurationProperty
private HuggingFace huggingFace;
@NestedConfigurationProperty
private LocalAi localAi;
@NestedConfigurationProperty
private InProcess inProcess;
public S2ModelProvider getProvider() {
return provider;
}
public void setProvider(S2ModelProvider provider) {
this.provider = provider;
}
public OpenAi getOpenAi() {
return openAi;
}
public void setOpenAi(OpenAi openAi) {
this.openAi = openAi;
}
public HuggingFace getHuggingFace() {
return huggingFace;
}
public void setHuggingFace(HuggingFace huggingFace) {
this.huggingFace = huggingFace;
}
public LocalAi getLocalAi() {
return localAi;
}
public void setLocalAi(LocalAi localAi) {
this.localAi = localAi;
}
public InProcess getInProcess() {
return inProcess;
}
public void setInProcess(InProcess inProcess) {
this.inProcess = inProcess;
}
}

View File

@@ -1,290 +0,0 @@
package dev.langchain4j;
import static dev.langchain4j.exception.IllegalConfigurationException.illegalConfiguration;
import static dev.langchain4j.internal.Utils.isNullOrBlank;
import dev.langchain4j.model.chat.ChatLanguageModel;
import dev.langchain4j.model.embedding.EmbeddingModel;
import dev.langchain4j.model.embedding.S2OnnxEmbeddingModel;
import dev.langchain4j.model.embedding.BgeSmallZhEmbeddingModel;
import dev.langchain4j.model.huggingface.HuggingFaceChatModel;
import dev.langchain4j.model.huggingface.HuggingFaceEmbeddingModel;
import dev.langchain4j.model.huggingface.HuggingFaceLanguageModel;
import dev.langchain4j.model.language.LanguageModel;
import dev.langchain4j.model.localai.LocalAiChatModel;
import dev.langchain4j.model.localai.LocalAiEmbeddingModel;
import dev.langchain4j.model.localai.LocalAiLanguageModel;
import dev.langchain4j.model.moderation.ModerationModel;
import dev.langchain4j.model.openai.FullOpenAiChatModel;
import dev.langchain4j.model.openai.OpenAiEmbeddingModel;
import dev.langchain4j.model.openai.OpenAiLanguageModel;
import dev.langchain4j.model.openai.OpenAiModerationModel;
import java.util.Objects;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Lazy;
import org.springframework.context.annotation.Primary;
@Configuration
@EnableConfigurationProperties(S2LangChain4jProperties.class)
public class S2LangChain4jAutoConfiguration {
@Autowired
private S2LangChain4jProperties properties;
@Bean
@Lazy
@ConditionalOnMissingBean
ChatLanguageModel chatLanguageModel(S2LangChain4jProperties properties) {
if (properties.getChatModel() == null) {
throw illegalConfiguration("\n\nPlease define 'langchain4j.chat-model' properties, for example:\n"
+ "langchain4j.chat-model.provider = openai\n"
+ "langchain4j.chat-model.openai.api-key = sk-...\n");
}
switch (properties.getChatModel().getProvider()) {
case OPEN_AI:
OpenAi openAi = properties.getChatModel().getOpenAi();
if (openAi == null || isNullOrBlank(openAi.getApiKey())) {
throw illegalConfiguration("\n\nPlease define 'langchain4j.chat-model.openai.api-key' property");
}
return FullOpenAiChatModel.builder()
.baseUrl(openAi.getBaseUrl())
.apiKey(openAi.getApiKey())
.modelName(openAi.getModelName())
.temperature(openAi.getTemperature())
.topP(openAi.getTopP())
.maxTokens(openAi.getMaxTokens())
.presencePenalty(openAi.getPresencePenalty())
.frequencyPenalty(openAi.getFrequencyPenalty())
.timeout(openAi.getTimeout())
.maxRetries(openAi.getMaxRetries())
.logRequests(openAi.getLogRequests())
.logResponses(openAi.getLogResponses())
.build();
case HUGGING_FACE:
HuggingFace huggingFace = properties.getChatModel().getHuggingFace();
if (huggingFace == null || isNullOrBlank(huggingFace.getAccessToken())) {
throw illegalConfiguration(
"\n\nPlease define 'langchain4j.chat-model.huggingface.access-token' property");
}
return HuggingFaceChatModel.builder()
.accessToken(huggingFace.getAccessToken())
.modelId(huggingFace.getModelId())
.timeout(huggingFace.getTimeout())
.temperature(huggingFace.getTemperature())
.maxNewTokens(huggingFace.getMaxNewTokens())
.returnFullText(huggingFace.getReturnFullText())
.waitForModel(huggingFace.getWaitForModel())
.build();
case LOCAL_AI:
LocalAi localAi = properties.getChatModel().getLocalAi();
if (localAi == null || isNullOrBlank(localAi.getBaseUrl())) {
throw illegalConfiguration("\n\nPlease define 'langchain4j.chat-model.localai.base-url' property");
}
if (isNullOrBlank(localAi.getModelName())) {
throw illegalConfiguration(
"\n\nPlease define 'langchain4j.chat-model.localai.model-name' property");
}
return LocalAiChatModel.builder()
.baseUrl(localAi.getBaseUrl())
.modelName(localAi.getModelName())
.temperature(localAi.getTemperature())
.topP(localAi.getTopP())
.maxTokens(localAi.getMaxTokens())
.timeout(localAi.getTimeout())
.maxRetries(localAi.getMaxRetries())
.logRequests(localAi.getLogRequests())
.logResponses(localAi.getLogResponses())
.build();
default:
throw illegalConfiguration("Unsupported chat model provider: %s",
properties.getChatModel().getProvider());
}
}
@Bean
@Lazy
@ConditionalOnMissingBean
LanguageModel languageModel(S2LangChain4jProperties properties) {
if (properties.getLanguageModel() == null) {
throw illegalConfiguration("\n\nPlease define 'langchain4j.language-model' properties, for example:\n"
+ "langchain4j.language-model.provider = openai\n"
+ "langchain4j.language-model.openai.api-key = sk-...\n");
}
switch (properties.getLanguageModel().getProvider()) {
case OPEN_AI:
OpenAi openAi = properties.getLanguageModel().getOpenAi();
if (openAi == null || isNullOrBlank(openAi.getApiKey())) {
throw illegalConfiguration(
"\n\nPlease define 'langchain4j.language-model.openai.api-key' property");
}
return OpenAiLanguageModel.builder()
.apiKey(openAi.getApiKey())
.baseUrl(openAi.getBaseUrl())
.modelName(openAi.getModelName())
.temperature(openAi.getTemperature())
.timeout(openAi.getTimeout())
.maxRetries(openAi.getMaxRetries())
.logRequests(openAi.getLogRequests())
.logResponses(openAi.getLogResponses())
.build();
case HUGGING_FACE:
HuggingFace huggingFace = properties.getLanguageModel().getHuggingFace();
if (huggingFace == null || isNullOrBlank(huggingFace.getAccessToken())) {
throw illegalConfiguration(
"\n\nPlease define 'langchain4j.language-model.huggingface.access-token' property");
}
return HuggingFaceLanguageModel.builder()
.accessToken(huggingFace.getAccessToken())
.modelId(huggingFace.getModelId())
.timeout(huggingFace.getTimeout())
.temperature(huggingFace.getTemperature())
.maxNewTokens(huggingFace.getMaxNewTokens())
.returnFullText(huggingFace.getReturnFullText())
.waitForModel(huggingFace.getWaitForModel())
.build();
case LOCAL_AI:
LocalAi localAi = properties.getLanguageModel().getLocalAi();
if (localAi == null || isNullOrBlank(localAi.getBaseUrl())) {
throw illegalConfiguration(
"\n\nPlease define 'langchain4j.language-model.localai.base-url' property");
}
if (isNullOrBlank(localAi.getModelName())) {
throw illegalConfiguration(
"\n\nPlease define 'langchain4j.language-model.localai.model-name' property");
}
return LocalAiLanguageModel.builder()
.baseUrl(localAi.getBaseUrl())
.modelName(localAi.getModelName())
.temperature(localAi.getTemperature())
.topP(localAi.getTopP())
.maxTokens(localAi.getMaxTokens())
.timeout(localAi.getTimeout())
.maxRetries(localAi.getMaxRetries())
.logRequests(localAi.getLogRequests())
.logResponses(localAi.getLogResponses())
.build();
default:
throw illegalConfiguration("Unsupported language model provider: %s",
properties.getLanguageModel().getProvider());
}
}
@Bean
@Lazy
@ConditionalOnMissingBean
@Primary
EmbeddingModel embeddingModel(S2LangChain4jProperties properties) {
if (properties.getEmbeddingModel() == null || properties.getEmbeddingModel().getProvider() == null) {
throw illegalConfiguration("\n\nPlease define 'langchain4j.embedding-model' properties, for example:\n"
+ "langchain4j.embedding-model.provider = openai\n"
+ "langchain4j.embedding-model.openai.api-key = sk-...\n");
}
switch (properties.getEmbeddingModel().getProvider()) {
case OPEN_AI:
OpenAi openAi = properties.getEmbeddingModel().getOpenAi();
if (openAi == null || isNullOrBlank(openAi.getApiKey())) {
throw illegalConfiguration(
"\n\nPlease define 'langchain4j.embedding-model.openai.api-key' property");
}
return OpenAiEmbeddingModel.builder()
.apiKey(openAi.getApiKey())
.baseUrl(openAi.getBaseUrl())
.modelName(openAi.getModelName())
.timeout(openAi.getTimeout())
.maxRetries(openAi.getMaxRetries())
.logRequests(openAi.getLogRequests())
.logResponses(openAi.getLogResponses())
.build();
case HUGGING_FACE:
HuggingFace huggingFace = properties.getEmbeddingModel().getHuggingFace();
if (huggingFace == null || isNullOrBlank(huggingFace.getAccessToken())) {
throw illegalConfiguration(
"\n\nPlease define 'langchain4j.embedding-model.huggingface.access-token' property");
}
return HuggingFaceEmbeddingModel.builder()
.accessToken(huggingFace.getAccessToken())
.modelId(huggingFace.getModelId())
.waitForModel(huggingFace.getWaitForModel())
.timeout(huggingFace.getTimeout())
.build();
case LOCAL_AI:
LocalAi localAi = properties.getEmbeddingModel().getLocalAi();
if (localAi == null || isNullOrBlank(localAi.getBaseUrl())) {
throw illegalConfiguration(
"\n\nPlease define 'langchain4j.embedding-model.localai.base-url' property");
}
if (isNullOrBlank(localAi.getModelName())) {
throw illegalConfiguration(
"\n\nPlease define 'langchain4j.embedding-model.localai.model-name' property");
}
return LocalAiEmbeddingModel.builder()
.baseUrl(localAi.getBaseUrl())
.modelName(localAi.getModelName())
.timeout(localAi.getTimeout())
.maxRetries(localAi.getMaxRetries())
.logRequests(localAi.getLogRequests())
.logResponses(localAi.getLogResponses())
.build();
case IN_PROCESS:
InProcess inProcess = properties.getEmbeddingModel().getInProcess();
if (Objects.isNull(inProcess) || isNullOrBlank(inProcess.getModelPath())) {
return new BgeSmallZhEmbeddingModel();
}
return new S2OnnxEmbeddingModel(inProcess.getModelPath(), inProcess.getVocabularyPath());
default:
throw illegalConfiguration("Unsupported embedding model provider: %s",
properties.getEmbeddingModel().getProvider());
}
}
@Bean
@Lazy
@ConditionalOnMissingBean
ModerationModel moderationModel(S2LangChain4jProperties properties) {
if (properties.getModerationModel() == null) {
throw illegalConfiguration("\n\nPlease define 'langchain4j.moderation-model' properties, for example:\n"
+ "langchain4j.moderation-model.provider = openai\n"
+ "langchain4j.moderation-model.openai.api-key = sk-...\n");
}
if (properties.getModerationModel().getProvider() != ModelProvider.OPEN_AI) {
throw illegalConfiguration("Unsupported moderation model provider: %s",
properties.getModerationModel().getProvider());
}
OpenAi openAi = properties.getModerationModel().getOpenAi();
if (openAi == null || isNullOrBlank(openAi.getApiKey())) {
throw illegalConfiguration("\n\nPlease define 'langchain4j.moderation-model.openai.api-key' property");
}
return OpenAiModerationModel.builder()
.apiKey(openAi.getApiKey())
.modelName(openAi.getModelName())
.timeout(openAi.getTimeout())
.maxRetries(openAi.getMaxRetries())
.logRequests(openAi.getLogRequests())
.logResponses(openAi.getLogResponses())
.build();
}
}

View File

@@ -1,49 +0,0 @@
package dev.langchain4j;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.context.properties.NestedConfigurationProperty;
@ConfigurationProperties(prefix = "s2.langchain4j")
public class S2LangChain4jProperties {
@NestedConfigurationProperty
private ChatModel chatModel;
@NestedConfigurationProperty
private LanguageModel languageModel;
@NestedConfigurationProperty
private S2EmbeddingModel embeddingModel;
@NestedConfigurationProperty
private ModerationModel moderationModel;
public ChatModel getChatModel() {
return chatModel;
}
public void setChatModel(ChatModel chatModel) {
this.chatModel = chatModel;
}
public LanguageModel getLanguageModel() {
return languageModel;
}
public void setLanguageModel(LanguageModel languageModel) {
this.languageModel = languageModel;
}
public S2EmbeddingModel getEmbeddingModel() {
return embeddingModel;
}
public void setEmbeddingModel(S2EmbeddingModel s2EmbeddingModel) {
this.embeddingModel = s2EmbeddingModel;
}
public ModerationModel getModerationModel() {
return moderationModel;
}
public void setModerationModel(ModerationModel moderationModel) {
this.moderationModel = moderationModel;
}
}

View File

@@ -1,30 +0,0 @@
package dev.langchain4j.model;
public enum ChatModel {
ZHIPU("glm"),
ALI("qwen");
private final String modelName;
private ChatModel(String modelName) {
this.modelName = modelName;
}
public String toString() {
return this.modelName;
}
public static ChatModel from(String stringValue) {
ChatModel[] var1 = values();
int var2 = var1.length;
for (int var3 = 0; var3 < var2; ++var3) {
ChatModel model = var1[var3];
if (model.modelName.equals(stringValue)) {
return model;
}
}
throw new IllegalArgumentException("Unknown role: '" + stringValue + "'");
}
}

View File

@@ -0,0 +1,15 @@
package dev.langchain4j.model.embedding;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class EmbeddingModelConfig {
@Bean
@ConditionalOnMissingBean
public EmbeddingModel embeddingModel() {
return new BgeSmallZhEmbeddingModel();
}
}

View File

@@ -1,12 +1,13 @@
package dev.langchain4j.model.embedding;
import org.apache.commons.lang3.StringUtils;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import org.apache.commons.lang3.StringUtils;
/**
* An embedding model that runs within your Java application's process.
@@ -51,7 +52,7 @@ public class S2OnnxEmbeddingModel extends AbstractInProcessEmbeddingModel {
try {
return new OnnxBertBiEncoder(
Files.newInputStream(pathToModel),
vocabularyFile,
vocabularyFile.openStream(),
PoolingMode.MEAN
);
} catch (IOException e) {

View File

@@ -1,227 +0,0 @@
package dev.langchain4j.model.openai;
import dev.ai4j.openai4j.OpenAiClient;
import dev.ai4j.openai4j.chat.ChatCompletionChoice;
import dev.ai4j.openai4j.chat.ChatCompletionRequest;
import dev.ai4j.openai4j.chat.ChatCompletionResponse;
import dev.ai4j.openai4j.chat.ChatCompletionRequest.Builder;
import dev.langchain4j.agent.tool.ToolSpecification;
import dev.langchain4j.data.message.AiMessage;
import dev.langchain4j.data.message.ChatMessage;
import dev.langchain4j.internal.RetryUtils;
import dev.langchain4j.internal.Utils;
import dev.langchain4j.model.ChatModel;
import dev.langchain4j.model.Tokenizer;
import dev.langchain4j.model.chat.ChatLanguageModel;
import dev.langchain4j.model.chat.TokenCountEstimator;
import dev.langchain4j.model.output.Response;
import java.net.Proxy;
import java.time.Duration;
import java.util.Collections;
import java.util.List;
public class FullOpenAiChatModel implements ChatLanguageModel, TokenCountEstimator {
private final OpenAiClient client;
private final String modelName;
private final Double temperature;
private final Double topP;
private final List<String> stop;
private final Integer maxTokens;
private final Double presencePenalty;
private final Double frequencyPenalty;
private final Integer maxRetries;
private final Tokenizer tokenizer;
public FullOpenAiChatModel(String baseUrl, String apiKey, String modelName, Double temperature,
Double topP, List<String> stop, Integer maxTokens, Double presencePenalty,
Double frequencyPenalty, Duration timeout, Integer maxRetries, Proxy proxy,
Boolean logRequests, Boolean logResponses, Tokenizer tokenizer) {
baseUrl = Utils.getOrDefault(baseUrl, "https://api.openai.com/v1");
if ("demo".equals(apiKey)) {
baseUrl = "http://langchain4j.dev/demo/openai/v1";
}
timeout = Utils.getOrDefault(timeout, Duration.ofSeconds(60L));
this.client = OpenAiClient.builder().openAiApiKey(apiKey)
.baseUrl(baseUrl).callTimeout(timeout).connectTimeout(timeout)
.readTimeout(timeout).writeTimeout(timeout).proxy(proxy)
.logRequests(logRequests).logResponses(logResponses).build();
this.modelName = Utils.getOrDefault(modelName, "gpt-3.5-turbo");
this.temperature = Utils.getOrDefault(temperature, 0.7D);
this.topP = topP;
this.stop = stop;
this.maxTokens = maxTokens;
this.presencePenalty = presencePenalty;
this.frequencyPenalty = frequencyPenalty;
this.maxRetries = Utils.getOrDefault(maxRetries, 3);
this.tokenizer = Utils.getOrDefault(tokenizer, new OpenAiTokenizer(this.modelName));
}
public Response<AiMessage> generate(List<ChatMessage> messages) {
return this.generate(messages, null, null);
}
public Response<AiMessage> generate(List<ChatMessage> messages, List<ToolSpecification> toolSpecifications) {
return this.generate(messages, toolSpecifications, null);
}
public Response<AiMessage> generate(List<ChatMessage> messages, ToolSpecification toolSpecification) {
return this.generate(messages, Collections.singletonList(toolSpecification), toolSpecification);
}
private Response<AiMessage> generate(List<ChatMessage> messages,
List<ToolSpecification> toolSpecifications,
ToolSpecification toolThatMustBeExecuted) {
Builder requestBuilder = null;
if (modelName.contains(ChatModel.ZHIPU.toString()) || modelName.contains(ChatModel.ALI.toString())) {
requestBuilder = ChatCompletionRequest.builder()
.model(this.modelName)
.messages(ImproveInternalOpenAiHelper.toOpenAiMessages(messages, this.modelName));
} else {
requestBuilder = ChatCompletionRequest.builder()
.model(this.modelName)
.messages(ImproveInternalOpenAiHelper.toOpenAiMessages(messages, this.modelName))
.temperature(this.temperature).topP(this.topP).stop(this.stop).maxTokens(this.maxTokens)
.presencePenalty(this.presencePenalty).frequencyPenalty(this.frequencyPenalty);
}
if (toolSpecifications != null && !toolSpecifications.isEmpty()) {
requestBuilder.functions(InternalOpenAiHelper.toFunctions(toolSpecifications));
}
if (toolThatMustBeExecuted != null) {
requestBuilder.functionCall(toolThatMustBeExecuted.name());
}
ChatCompletionRequest request = requestBuilder.build();
ChatCompletionResponse response = (ChatCompletionResponse) RetryUtils.withRetry(() -> {
return (ChatCompletionResponse) this.client.chatCompletion(request).execute();
}, this.maxRetries);
return Response.from(InternalOpenAiHelper.aiMessageFrom(response),
InternalOpenAiHelper.tokenUsageFrom(response.usage()),
InternalOpenAiHelper.finishReasonFrom(
((ChatCompletionChoice) response.choices().get(0)).finishReason()));
}
public int estimateTokenCount(List<ChatMessage> messages) {
return this.tokenizer.estimateTokenCountInMessages(messages);
}
public static FullOpenAiChatModel.FullOpenAiChatModelBuilder builder() {
return new FullOpenAiChatModel.FullOpenAiChatModelBuilder();
}
public static class FullOpenAiChatModelBuilder {
private String baseUrl;
private String apiKey;
private String modelName;
private Double temperature;
private Double topP;
private List<String> stop;
private Integer maxTokens;
private Double presencePenalty;
private Double frequencyPenalty;
private Duration timeout;
private Integer maxRetries;
private Proxy proxy;
private Boolean logRequests;
private Boolean logResponses;
private Tokenizer tokenizer;
FullOpenAiChatModelBuilder() {
}
public FullOpenAiChatModel.FullOpenAiChatModelBuilder baseUrl(String baseUrl) {
this.baseUrl = baseUrl;
return this;
}
public FullOpenAiChatModel.FullOpenAiChatModelBuilder apiKey(String apiKey) {
this.apiKey = apiKey;
return this;
}
public FullOpenAiChatModel.FullOpenAiChatModelBuilder modelName(String modelName) {
this.modelName = modelName;
return this;
}
public FullOpenAiChatModel.FullOpenAiChatModelBuilder temperature(Double temperature) {
this.temperature = temperature;
return this;
}
public FullOpenAiChatModel.FullOpenAiChatModelBuilder topP(Double topP) {
this.topP = topP;
return this;
}
public FullOpenAiChatModel.FullOpenAiChatModelBuilder stop(List<String> stop) {
this.stop = stop;
return this;
}
public FullOpenAiChatModel.FullOpenAiChatModelBuilder maxTokens(Integer maxTokens) {
this.maxTokens = maxTokens;
return this;
}
public FullOpenAiChatModel.FullOpenAiChatModelBuilder presencePenalty(Double presencePenalty) {
this.presencePenalty = presencePenalty;
return this;
}
public FullOpenAiChatModel.FullOpenAiChatModelBuilder frequencyPenalty(Double frequencyPenalty) {
this.frequencyPenalty = frequencyPenalty;
return this;
}
public FullOpenAiChatModel.FullOpenAiChatModelBuilder timeout(Duration timeout) {
this.timeout = timeout;
return this;
}
public FullOpenAiChatModel.FullOpenAiChatModelBuilder maxRetries(Integer maxRetries) {
this.maxRetries = maxRetries;
return this;
}
public FullOpenAiChatModel.FullOpenAiChatModelBuilder proxy(Proxy proxy) {
this.proxy = proxy;
return this;
}
public FullOpenAiChatModel.FullOpenAiChatModelBuilder logRequests(Boolean logRequests) {
this.logRequests = logRequests;
return this;
}
public FullOpenAiChatModel.FullOpenAiChatModelBuilder logResponses(Boolean logResponses) {
this.logResponses = logResponses;
return this;
}
public FullOpenAiChatModel.FullOpenAiChatModelBuilder tokenizer(Tokenizer tokenizer) {
this.tokenizer = tokenizer;
return this;
}
public FullOpenAiChatModel build() {
return new FullOpenAiChatModel(this.baseUrl, this.apiKey, this.modelName, this.temperature,
this.topP, this.stop, this.maxTokens, this.presencePenalty, this.frequencyPenalty,
this.timeout, this.maxRetries, this.proxy, this.logRequests, this.logResponses, this.tokenizer);
}
public String toString() {
return "FullOpenAiChatModel.FullOpenAiChatModelBuilder(baseUrl=" + this.baseUrl
+ ", apiKey=" + this.apiKey + ", modelName=" + this.modelName + ", temperature="
+ this.temperature + ", topP=" + this.topP + ", stop=" + this.stop + ", maxTokens="
+ this.maxTokens + ", presencePenalty=" + this.presencePenalty + ", frequencyPenalty="
+ this.frequencyPenalty + ", timeout=" + this.timeout + ", maxRetries=" + this.maxRetries
+ ", proxy=" + this.proxy + ", logRequests=" + this.logRequests + ", logResponses="
+ this.logResponses + ", tokenizer=" + this.tokenizer + ")";
}
}
}

View File

@@ -1,66 +0,0 @@
package dev.langchain4j.model.openai;
import dev.ai4j.openai4j.chat.FunctionCall;
import dev.ai4j.openai4j.chat.Message;
import dev.ai4j.openai4j.chat.Role;
import dev.langchain4j.data.message.AiMessage;
import dev.langchain4j.data.message.ChatMessage;
import dev.langchain4j.data.message.SystemMessage;
import dev.langchain4j.data.message.ToolExecutionResultMessage;
import dev.langchain4j.data.message.UserMessage;
import dev.langchain4j.model.ChatModel;
import java.util.List;
import java.util.stream.Collectors;
public class ImproveInternalOpenAiHelper {
public ImproveInternalOpenAiHelper() {
}
public static List<Message> toOpenAiMessages(List<ChatMessage> messages, String modelName) {
List<Message> messageList = messages.stream()
.map(message -> toOpenAiMessage(message, modelName)).collect(Collectors.toList());
return messageList;
}
public static Message toOpenAiMessage(ChatMessage message, String modelName) {
return Message.builder().role(roleFrom(message, modelName))
.name(nameFrom(message)).content(message.text())
.functionCall(functionCallFrom(message)).build();
}
private static String nameFrom(ChatMessage message) {
if (message instanceof UserMessage) {
return ((UserMessage) message).name();
} else {
return message instanceof ToolExecutionResultMessage
? ((ToolExecutionResultMessage) message).toolName() : null;
}
}
private static FunctionCall functionCallFrom(ChatMessage message) {
if (message instanceof AiMessage) {
AiMessage aiMessage = (AiMessage) message;
if (aiMessage.toolExecutionRequest() != null) {
return FunctionCall.builder().name(aiMessage.toolExecutionRequest().name())
.arguments(aiMessage.toolExecutionRequest().arguments()).build();
}
}
return null;
}
public static Role roleFrom(ChatMessage message, String modelName) {
if (modelName.contains(ChatModel.ZHIPU.toString()) || modelName.contains(ChatModel.ALI.toString())) {
return Role.USER;
}
if (message instanceof AiMessage) {
return Role.ASSISTANT;
} else if (message instanceof ToolExecutionResultMessage) {
return Role.FUNCTION;
} else {
return message instanceof SystemMessage ? Role.SYSTEM : Role.USER;
}
}
}

View File

@@ -86,7 +86,7 @@ public class InMemoryS2EmbeddingStore implements S2EmbeddingStore {
@Override
public void addQuery(String collectionName, List<EmbeddingQuery> queries) {
InMemoryEmbeddingStore<EmbeddingQuery> embeddingStore = getEmbeddingStore(collectionName);
EmbeddingModel embeddingModel = ContextUtils.getBean(EmbeddingModel.class);
EmbeddingModel embeddingModel = getEmbeddingModel();
for (EmbeddingQuery query : queries) {
String question = query.getQuery();
Embedding embedding = embeddingModel.embed(question).content();
@@ -94,6 +94,10 @@ public class InMemoryS2EmbeddingStore implements S2EmbeddingStore {
}
}
private static EmbeddingModel getEmbeddingModel() {
return ContextUtils.getBean(EmbeddingModel.class);
}
private InMemoryEmbeddingStore<EmbeddingQuery> getEmbeddingStore(String collectionName) {
InMemoryEmbeddingStore<EmbeddingQuery> embeddingStore = collectionNameToStore.get(collectionName);
if (Objects.isNull(embeddingStore)) {
@@ -113,7 +117,7 @@ public class InMemoryS2EmbeddingStore implements S2EmbeddingStore {
@Override
public List<RetrieveQueryResult> retrieveQuery(String collectionName, RetrieveQuery retrieveQuery, int num) {
InMemoryEmbeddingStore<EmbeddingQuery> embeddingStore = getEmbeddingStore(collectionName);
EmbeddingModel embeddingModel = ContextUtils.getBean(EmbeddingModel.class);
EmbeddingModel embeddingModel = getEmbeddingModel();
List<RetrieveQueryResult> results = new ArrayList<>();