Skip to content

Commit

Permalink
Supports functions HamaWhiteGG#133
Browse files Browse the repository at this point in the history
  • Loading branch information
HamaWhiteGG committed Nov 30, 2023
1 parent b5a5806 commit 56141f6
Show file tree
Hide file tree
Showing 21 changed files with 866 additions and 4 deletions.
6 changes: 6 additions & 0 deletions langchain-core/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,12 @@
<dependency>
<groupId>org.redisson</groupId>
<artifactId>redisson</artifactId>
<exclusions>
<exclusion>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
</exclusion>
</exclusions>
</dependency>

<dependency>
Expand Down
10 changes: 10 additions & 0 deletions openai-client/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,16 @@
<artifactId>jackson-annotations</artifactId>
</dependency>

<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
</dependency>

<dependency>
<groupId>com.fasterxml.jackson.module</groupId>
<artifactId>jackson-module-parameter-names</artifactId>
</dependency>

<dependency>
<groupId>org.hibernate.validator</groupId>
<artifactId>hibernate-validator</artifactId>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,12 @@ public class ChatChoice {
@JsonAlias("delta")
private Message message;

/**
* The reason the model stopped generating tokens. This will be stopped if the model hit a natural stop point or a
* provided stop sequence, length if the maximum number of tokens specified in the request was reached,
* content_filter if content was omitted due to a flag from our content filters, tool_calls if the model called a
* tool, or function_call (deprecated) if the model called a function.
*/
@JsonProperty("finish_reason")
private String finishReason;
}
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,12 @@ public class ChatCompletion implements Serializable {
*/
private boolean stream;

/**
* This feature is in Beta. If specified, our system will make a best effort to sample deterministically,
* such that repeated requests with the same seed and parameters should return the same result.
*/
private Integer seed;

/**
* Up to 4 sequences where the API will stop generating further tokens.
*/
Expand Down Expand Up @@ -119,4 +125,19 @@ public class ChatCompletion implements Serializable {
* A unique identifier representing your end-user, which can help OpenAI to monitor and detect abuse.
*/
private String user;

/**
* A list of tools the model may call. Currently, only functions are supported as a tool.
* Use this to provide a list of functions the model may generate JSON inputs for.
*/
private List<Tool> tools;

/**
* Controls which (if any) function is called by the model. none means the model will not call a function and
* instead generates a message.
* <p>
* none is the default when no functions are present. auto is the default if functions are present.
*/
@JsonProperty("tool_choice")
private String toolChoice;
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@

package com.hw.openai.entity.chat;

import com.fasterxml.jackson.annotation.JsonProperty;
import com.hw.openai.entity.completions.Usage;

import lombok.Data;
Expand All @@ -39,6 +40,13 @@ public class ChatCompletionResp {

private String model;

/**
* This fingerprint represents the backend configuration that the model runs with. Can be used in conjunction with
* the seed request parameter to understand when backend changes have been made that might impact determinism.
*/
@JsonProperty("system_fingerprint")
private String systemFingerprint;

private List<ChatChoice> choices;

private Usage usage;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package com.hw.openai.entity.chat;

import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.databind.node.ObjectNode;

import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;

import java.util.List;

/**
* @author HamaWhite
*/
@Data
@Builder
@JsonInclude(JsonInclude.Include.NON_NULL)
public class ChatFunction {

/**
* The name of the function to be called. Must be a-z, A-Z, 0-9, or contain underscores and dashes,
* with a maximum length of 64.
*/
@NotBlank
private String name;

/**
* A description of what the function does, used by the model to choose when and how to call the function.
*/
private String description;

/**
* The parameters the functions accepts, described as a JSON Schema object.
* To describe a function that accepts no parameters, provide the value {"type": "object", "properties": {}}
*/
@NotNull
private ChatParameter parameters;

@Data
@NoArgsConstructor
@JsonInclude(JsonInclude.Include.NON_NULL)
public static class ChatParameter {

private String type;

private ObjectNode properties;

private List<String> required;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package com.hw.openai.entity.chat;

import lombok.Data;

/**
* @author HamaWhite
*/
@Data
public class Function {

/**
* The name of the function to call.
*/
private String name;

/**
* The arguments to call the function with, as generated by the model in JSON format.
* Note that the model does not always generate valid JSON, and may hallucinate parameters not defined by your
* function schema. Validate the arguments in your code before calling your function.
*/
private String arguments;
}
14 changes: 14 additions & 0 deletions openai-client/src/main/java/com/hw/openai/entity/chat/Message.java
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
package com.hw.openai.entity.chat;

import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonProperty;

import jakarta.validation.constraints.NotNull;
import lombok.AllArgsConstructor;
Expand All @@ -27,6 +28,7 @@
import lombok.NoArgsConstructor;

import java.io.Serializable;
import java.util.List;

/**
* Message
Expand Down Expand Up @@ -59,11 +61,23 @@ public class Message implements Serializable {
*/
private String name;

/**
* The name and arguments of a function that should be called, as generated by the model.
*/
@JsonProperty("tool_calls")
private List<ToolCall> toolCalls;

public Message(Role role, String content) {
this.role = role;
this.content = content;
}

public Message(Role role, String content, String name) {
this.role = role;
this.content = content;
this.name = name;
}

public static Message of(String role, String content) {
return new Message(Role.fromValue(role), content);
}
Expand Down
43 changes: 43 additions & 0 deletions openai-client/src/main/java/com/hw/openai/entity/chat/Tool.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package com.hw.openai.entity.chat;

import com.fasterxml.jackson.annotation.JsonProperty;

import lombok.Data;

/**
* @author HamaWhite
*/

@Data
public class Tool {

/**
* The type of the tool. Currently, only function is supported.
*/
private String type = "function";

@JsonProperty("function")
private ChatFunction chatFunction;

public Tool(ChatFunction chatFunction) {
this.chatFunction = chatFunction;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package com.hw.openai.entity.chat;

import lombok.Data;

/**
* @author HamaWhite
*/
@Data
public class ToolCall {

private Integer index;

/**
* The ID of the tool call.
*/
private String id;

/**
* The type of the tool. Currently, only function is supported.
*/
private String type;

private Function function;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package com.hw.openai.function;

import java.util.HashMap;
import java.util.Map;
import java.util.function.Function;

import static com.hw.openai.utils.JsonUtils.convertFromJsonStr;

/**
* @author HamaWhite
*/
public class FunctionExecutor {

private static final Map<String, Function<?, ?>> FUNCTION_MAP = new HashMap<>(16);

public static <T> void register(String functionName, Function<T, ?> function) {
FUNCTION_MAP.put(functionName, function);
}

@SuppressWarnings("unchecked")
public static <T, R> R execute(String functionName, Class<T> clazz, String arguments) throws ClassCastException {
Function<T, R> function = (Function<T, R>) FUNCTION_MAP.get(functionName);
if (function == null) {
throw new IllegalArgumentException("No function registered with name: " + functionName);
}
T input = convertFromJsonStr(arguments, clazz);
return function.apply(input);
}
}
Loading

0 comments on commit 56141f6

Please sign in to comment.