Giter VIP home page Giter VIP logo

lambdua / openai4j Goto Github PK

View Code? Open in Web Editor NEW
294.0 294.0 22.0 1.28 MB

Java client library for OpenAI API.Full support for all OpenAI API models including Completions, Chat, Edits, Embeddings, Audio, Files, Assistants-v2, Images, Moderations, Batch, and Fine-tuning.

License: MIT License

Java 99.99% HTML 0.01%
assistants-api chatgpt chatgpt4 gpt-4o gpt-4o-api gpt-vision gpt4 openai openai-api openai-api-chatbot openai-assistant-api openai-images openai-whisper

openai4j's Introduction

github contribution grid snake animation

🥱关于我

  • coder

☕技术栈

  • java
  • spring全家桶
  • python
  • mongo,mysql,redis...

openai4j's People

Contributors

aaronuu avatar bertilmuth avatar bjorkman avatar danielfariati avatar dehidehidehi avatar drakeet avatar eduardo-t avatar fchebbo avatar gianseb avatar grogdunn avatar hawkan avatar izeye avatar lambdua avatar mrblw avatar mzhu-ai avatar nahakiole avatar ran-mewo avatar remyohajinwa avatar rijekadrina avatar ronilbhattarai avatar runningcode avatar sliman4 avatar teerapap avatar tgolob avatar theokanning avatar tox-p avatar vacuityv avatar venthe avatar widoriezebos avatar yeikel avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar

openai4j's Issues

new `FunctionDefinition` incompatible with azure

Using the new FunctionDefinition returns this on azure's gpt-4-turbo

  "error": {
    "message": "1 validation error for Request\nbody -> tools\n  extra fields not permitted (type=value_error.extra)",
    "type": "invalid_request_error",
    "param": null,
    "code": null
  }

Looking at the converted JSON (I used ObjectMapper().writeValueAsString so I am not sure if it's accurate)

{
    "type": "function",
    "function": {
      "name": "wolframAlpha",
      "description": "Computes mathematical expressions using WolframAlpha",
      "parameters": {
        "$schema": "http://json-schema.org/draft-04/schema#",
        "title": "Wolfram Alpha Function",
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "input": {
            "type": "string"
          }
        }
      }
    }
  }

seems like azure doesn't support the "$schema", "title", "aditionalProperties" fields as I can't find these in any documentation

another limitation with the new FunctionDefinition is that it doesn't allow parameterless functions, the parameters field is optional and can be omitted

Omitting parameters defines a function with an empty parameter list.

反序列化ChatCompletionRequest对象失败

我在尝试将接收到的JSON请求体反序列化为ChatCompletionRequest对象时遇到了问题。尽管我发送的请求数据格式看起来是正确的,但是反序列化过程没有成功。

请求示例
{
"topP": 1,
"temperature": 1,
"maxTokens": 2500,
"messages": [
{
"role": "system",
"content": "你好"
},
{
"role": "user",
"content": [
{
"type": "text",
"text": "识别这张图片"
},
{
"type": "image_url",
"imageUrl": {
"url": "https://img.baigonglian.com/open_platform/generate/1ad71539c74715cfceb1c6b2634e9bf1.png"
}
}
]
}
],
"model": "gpt-4o",
"frequencyPenalty": 0.6299999952316284
}

Implement list of threads

Is it possible to implement GET in the threads API to find out all the threads you created.

It seems to be possible also if not officially documented using the following example:

def list_threads(api_key):
response = requests.get(
'https://api.openai.com/v1/threads?order=desc&limit=20',
headers={
'Content-Type': 'application/json',
'Authorization': f'Bearer {api_key}',
'OpenAI-Beta': 'assistants=v1'
}
)
if response.status_code == 200:
return response.json()['data']
return None

Please consider this new feature in the next release. Thanks

FileSearchTool deserialization exception: Cannot deserialize value of type `java.lang.String` from Object value (token `JsonToken.START_OBJECT`)

com.fasterxml.jackson.databind.exc.MismatchedInputException: Cannot deserialize value of type `java.lang.String` from Object value (token `JsonToken.START_OBJECT`)
 at [Source: (String)"{"id":"step_UZoC1MNqKPZ3VcuG2r2k","object":"thread.run.step.delta","delta":{"step_details":{"type":"tool_calls","tool_calls":[{"index":0,"id":"call_mYpvxh6V0XygaLpz1FX","type":"file_search","file_search":{"ranking_options":{"ranker":"default_2024_08_21","score_threshold":0.0},"results":[]}}]}}}"; line: 1, column: 233] (through reference chain: com.theokanning.openai.assistants.run_step.RunStepDelta["delta"]->com.theokanning.openai.assistants.run_step.Delta["step_details"]->com.theokanning.openai.assistants.run_step.StepDetails["tool_calls"]->java.util.ArrayList[0]->com.theokanning.openai.assistants.run.ToolCall["file_search"]->java.util.LinkedHashMap["ranking_options"])

"type":"file_search","file_search":{"ranking_options":{"ranker":"default_2024_08_21","score_threshold":0.0}

Class FileSearchTool needs to add the ranking_options field.

https://platform.openai.com/docs/assistants/tools/file-search/improve-file-search-result-relevance-with-chunk-ranking

Issues while switching over from TheoKanning/openai-java

We have been using TheoKanning/openai-java in our service. Since that is not being maintained anymore, we thought of switching over to this project.

One immediate issue we encountered was deprecation warning here

What is the recommended alternative to TikTokensUtil.java ?
We want to count tokens before hand to make a decision whether to even make a request to open ai or not.

如何解决chatgpt4 上下文的问题呢

我现在会把之前的历史都发给gpt,但是回复的好像有问题
第一次问的是,使用Java读取excel,
第二次问的你好,然后也会把第一次记录发送给gpt,返回的是这种

image

使用assistant file_search时,如果回复有文件的引用,则会发生Unknown event name: thread.run.incomplete

文档关联到assistant,启用file_search和stream

[LogHandler] SSE: {"id":"msg_xxx","object":"thread.message.delta","delta":{"content":[{"index":0,"type":"text","text":{"value":"【272:4†source】","annotations":[{"index":0,"type":"file_citation","text":"【272:4†source】","start_index":357,"end_index":371,"file_citation":{"file_id":"file-xxx","quote":""}}]}}]}} event: THREAD_MESSAGE_DELTA
[LogHandler] SSE: {"id":"msg_xxx","object":"thread.message.delta","delta":{"content":[{"index":0,"type":"text","text":{"value":"."}}]}} event: THREAD_MESSAGE_DELTA
[LogHandler] SSE: {"id":"msg_xxx","object":"thread.message","created_at":1723696331,"assistant_id":"asst_xxx","thread_id":"thread_xxx","run_id":"run_xxx","status":"completed","incomplete_details":null,"incomplete_at":null,"completed_at":1723696333,"role":"assistant","content":[{"type":"text","text":{"value":"To ... on【272:4†source】.","annotations":[{"type":"file_citation","text":"【272:4†source】","start_index":357,"end_index":371,"file_citation":{"file_id":"file-xxx"}}]}}],"attachments":[],"metadata":{}} event: THREAD_MESSAGE_COMPLETED
[LogHandler] message completed
[LogHandler] SSE: {"id":"step_xxx","object":"thread.run.step","created_at":1723696331,"run_id":"run_xxx","assistant_id":"asst_xxx","thread_id":"thread_xxx","type":"message_creation","status":"completed","cancelled_at":null,"completed_at":1723696333,"expires_at":1723696927,"failed_at":null,"last_error":null,"step_details":{"type":"message_creation","message_creation":{"message_id":"msg_xxx"}},"usage":{"prompt_tokens":6064,"completion_tokens":92,"total_tokens":6156}} event: THREAD_RUN_STEP_COMPLETED
[LogHandler] error: Unknown event name: thread.run.incomplete

如果没有【272:4†source】等类似标注的回复,就不会发生这个错误

More user-friendly way to create image messages from local image files

Creating an user image message from a URL is straight forward using UserMessage.buildImageMessage.

Creating an user image message from a local image file is much more tedious, here's some sample code:

public void postDiagramImage(String userMessageText, Path diagramImagePath) {
  List<ChatMessage> messages = ...
  UserMessage imageMessage = createImageMessage(userMessageText, diagramImagePath);
  messages.add(imageMessage);
  ...
}

private UserMessage createImageMessage(String userMessageText, Path imagePath) {
  ImageContent userMessageContent = new ImageContent(userMessageText);
  String imagePathString = imagePath.toAbsolutePath().toString();
  String extension = imagePathString.substring(imagePathString.lastIndexOf('.') + 1);
  String imageUrl = "data:image/" + extension + ";base64," + encodeImage(imagePath);
  ImageContent imageContent = new ImageContent(new ImageUrl(imageUrl));
  UserMessage imageMessage = new UserMessage(List.of(userMessageContent, imageContent));
  return imageMessage;
}
	
private String encodeImage(Path imagePath) {
  byte[] fileContent;
      try {
            fileContent = Files.readAllBytes(imagePath);
            return Base64.getEncoder().encodeToString(fileContent);
      } catch (IOException e){
        throw new RuntimeException(e);
      }
}

It would be great if code like this could be encapsulated, and provided to the user in a friendly manner.

标准的 Openai ChatCompletion JSON 参数字符串没法转成 ChatCompletionRequest

看异常应该是有些字段的序列化方式没设置对。

重现测试用例:

public class ChatCompletionExample {

    private static final String BASE_URL = "https://api.openai.com/v1/";
    private static final String API_KEY = "sk-1234567890";

    private static final ObjectMapper objectMapper = new ObjectMapper();

    public static void main(String[] args) throws JsonProcessingException {
        String json = "{\"model\":\"gpt-4o-mini\",\"max_tokens\":150,\"response_format\":{\"type\":\"json_object\"},\"messages\":[{\"role\":\"system\",\"content\":\"You are a helpful assistant and you should reply in JSON format.\"},{\"role\":\"user\",\"content\":\"What is your name?\"}]}";
        ChatCompletionRequest completionRequest = objectMapper.readValue(json, ChatCompletionRequest.class);
        OpenAiService openAiService = new OpenAiService(API_KEY, BASE_URL);
        ChatCompletionResult completionResult = openAiService.createChatCompletion(completionRequest);
        System.out.println(completionResult);
    }
}

报了如下异常:

Exception in thread "main" com.fasterxml.jackson.databind.exc.MismatchedInputException: Cannot construct instance of `com.theokanning.openai.completion.chat.ChatResponseFormat` (although at least one Creator exists): cannot deserialize from Object value (no delegate- or property-based Creator)
 at [Source: (String)"{"model":"gpt-4o-mini","max_tokens":150,"response_format":{"type":"json_object"},"messages":[{"role":"system","content":"You are a helpful assistant and you should reply in JSON format."},{"role":"user","content":"What is your name?"}]}"; line: 1, column: 60] (through reference chain: com.theokanning.openai.completion.chat.ChatCompletionRequest["response_format"])
	at com.fasterxml.jackson.databind.exc.MismatchedInputException.from(MismatchedInputException.java:63)
	at com.fasterxml.jackson.databind.DeserializationContext.reportInputMismatch(DeserializationContext.java:1733)
	at com.fasterxml.jackson.databind.DeserializationContext.handleMissingInstantiator(DeserializationContext.java:1358)
	at com.fasterxml.jackson.databind.deser.BeanDeserializerBase.deserializeFromObjectUsingNonDefault(BeanDeserializerBase.java:1420)
	at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserializeFromObject(BeanDeserializer.java:352)
	at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:185)
	at com.fasterxml.jackson.databind.deser.impl.MethodProperty.deserializeAndSet(MethodProperty.java:129)
	at com.fasterxml.jackson.databind.deser.BeanDeserializer.vanillaDeserialize(BeanDeserializer.java:314)
	at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:177)
	at com.fasterxml.jackson.databind.deser.DefaultDeserializationContext.readRootValue(DefaultDeserializationContext.java:323)
	at com.fasterxml.jackson.databind.ObjectMapper._readMapAndClose(ObjectMapper.java:4730)
	at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:3677)
	at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:3645)
	at example.ChatCompletionExample.main(ChatCompletionExample.java:21)

streaming方式获取function call的argument

执行测试用例时,对应messageChunk获取的arguments类型还是objectNode,导致解析为空
image
我需要在初始化时做什么操作吗,设定不同的序列化方式?

报错 java.lang.ClassNotFoundException: com.fasterxml.jackson.databind.PropertyNamingStrategies

service version

0.20.1

<dependency>
  <groupId>io.github.lambdua</groupId>
  <artifactId>service</artifactId>
  <version>0.20.1</version>
</dependency>

异常信息:

java.lang.ClassNotFoundException: com.fasterxml.jackson.databind.PropertyNamingStrategies
	at java.net.URLClassLoader.findClass(URLClassLoader.java:382)
	at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
	at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
	at com.theokanning.openai.service.OpenAiService.defaultObjectMapper(OpenAiService.java:180)
	at com.theokanning.openai.service.OpenAiService.<clinit>(OpenAiService.java:82)
	

image

StreamOption.includeUsage = true causes OpenAiService.mapStreamToAccumulator to throw java.lang.IndexOutOfBoundsException

When StreamOption.includeUsage = true, the last usage chunk contains no choices, resulting in an IndexOutOfBoundsException.

Example of the Last Usage Chunk:
{ "id": "chatcmpl-A4yfRYHaCuVyGtk5r0DnV9donhXja", "object": "chat.completion.chunk", "created": 1725749881, "model": "gpt-4o-2024-05-13", "choices": [], "usage": { "prompt_tokens": 611, "completion_tokens": 13, "total_tokens": 624 }, "system_fingerprint": "fp_992d1ea92d" }

The OpenAiService.mapStreamToAccumulator method attempts to access the first choice in the choices array with the following code:
ChatCompletionChoice firstChoice = chunk.getChoices().get(0);

However, this code assumes that there is always at least one choice available. When choices is empty, this leads to a java.lang.IndexOutOfBoundsException.

Although my understanding of the model is limited, it seems reasonable to either:

  1. Ignore the usage chunk during mapStreamToAccumulator.
  2. Add usage data to AssistantMessage model

JsonUtil improvement

Hi @Lambdua, I'm using your library specially for the Assistants API. Since yesterday the added a parallel_tool_calls param, I am getting this error:

Caused by: com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException: Unrecognized field "parallel_tool_calls" (class com.theokanning.openai.assistants.run.Run), not marked as ignorable...

What I did locally as a workaround was to make the JsonUtil internal Mapper a bit more robust, so that unknown properties would not make the parsing fail:

private static class ObjectMapperHolder {
		private static final ObjectMapper MAPPER = new ObjectMapper();
		static {
			MAPPER.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
			MAPPER.setSerializationInclusion(JsonInclude.Include.NON_NULL);
			MAPPER.setPropertyNamingStrategy(PropertyNamingStrategies.LOWER_CAMEL_CASE);
		}
	}

What do you think of this change?

Assistant Message and image_url

When using this code:

Run run = service.createThreadAndRun(CreateThreadAndRunRequest.builder()
.assistantId(assistantId)
.thread(ThreadRequest.builder()
.messages(Collections.singletonList(
MessageRequest.builder()
.content(Arrays.asList(
new ImageContent("这个图片里面描述了什么?"),
new ImageContent(new ImageUrl("https://upload.wikimedia.org/wikipedia/commons/thumb/d/dd/Gfp-wisconsin-madison-the-nature-boardwalk.jpg/2560px-Gfp-wisconsin-madison-the-nature-boardwalk.jpg"))
))
.build()))
.build())
.build());
threadId= run.getThreadId();
Run retrievedRun = service.retrieveRun(run.getThreadId(), run.getId());
while (!(retrievedRun.getStatus().equals("completed"))
&& !(retrievedRun.getStatus().equals("failed"))
&& !(retrievedRun.getStatus().equals("expired"))
&& !(retrievedRun.getStatus().equals("incomplete"))
&& !(retrievedRun.getStatus().equals("requires_action"))) {
retrievedRun = service.retrieveRun(threadId, run.getId());
}
OpenAiResponse<Message> response = service.listMessages(threadId, MessageListSearchParameters.builder().runId(retrievedRun.getId()).build());
List<Message> data = response.getData();
assertTrue(!data.isEmpty());

The messages returned from listMessages don't have an ImageUrl object. They only have a MessageContent object with type image_url but no image_url. The Assistant Playground does show that this data is returned from the API when listing thread messages.

Is it possibly because the messages returned from the Threads API are being coerced to Assistant MessageContent which doesn't cater for image_url?

ImageContent from byte array or input stream

I think there is no documentation about how to send Image from ByteArray or Stream... but I think the ChatGPT allow this ? It is possible to send by url or "text"... what is a text image ??
Thank you for this great API !

Do you need to switch to a higher version of JDK?

I am the maintainer of this open-source library, and I developed it based on the openai Java library. Currently, the JDK 8 version is no longer suitable for my own needs. I have the idea of upgrading to a higher version of the JDK to use more of its features
However, this idea depends on the thoughts of the people using this library. I hope those who see this issue can provide their own opinions

支持添加default_headers吗?

感谢作者开源openai4j.

我使用CloudFlare 的AI GateWay 代理的Azure OpenAI.
需要填写defalut_header 和 deafalut_query.

OpenAI的官方python库是支持这个添加的。
image

我想问下这个库是否支持?
如果不支持的话,能否指导一下如何修改代码?
非常感谢。

Safe Structured Outputs `refusal` field add

a new refusal string value on API responses which allows developers to programmatically detect if the model has generated a refusal instead of output matching the schema. When the response does not include a refusal and the model’s response has not been prematurely interrupted (as indicated by finish_reason), then the model’s response will reliably produce valid JSON matching the supplied schema.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.