diff --git a/Makefile b/Makefile index 47a9fd9..2753d0e 100644 --- a/Makefile +++ b/Makefile @@ -29,10 +29,10 @@ list-releases: --compressed \ --silent | jq -r '.components[].version' -docs: +docs-build: npm i --prefix docs && npm run build --prefix docs -docs-dev: +docs-serve: npm i --prefix docs && npm run start --prefix docs start-cpu: diff --git a/docs/blog/2023-12-01-welcome/index.md b/docs/blog/2023-12-01-welcome/index.md deleted file mode 100644 index 5d74320..0000000 --- a/docs/blog/2023-12-01-welcome/index.md +++ /dev/null @@ -1,9 +0,0 @@ ---- -slug: welcome -title: Welcome -authors: [ amith ] -tags: [ Java, AI, LLM, GenAI, GenerativeAI, Ollama, Ollama4J, OpenSource, Developers -] ---- - -Welcome Java Developers! diff --git a/docs/blog/2023-12-22-release-post.md b/docs/blog/2023-12-22-release-post.md index aba2a53..070b515 100644 --- a/docs/blog/2023-12-22-release-post.md +++ b/docs/blog/2023-12-22-release-post.md @@ -1,6 +1,6 @@ --- slug: release-post -title: Release +title: First Release 🚀 authors: [ amith ] tags: [ Java, AI, LLM, GenAI, GenerativeAI, Ollama, Ollama4j, OpenSource, Developers ] diff --git a/docs/docs/apis-generate/chat-with-tools.md b/docs/docs/apis-generate/chat-with-tools.md new file mode 100644 index 0000000..577c26e --- /dev/null +++ b/docs/docs/apis-generate/chat-with-tools.md @@ -0,0 +1,69 @@ +--- +sidebar_position: 8 +--- + +import CodeEmbed from '@site/src/components/CodeEmbed'; + +# Chat with Tools + +### Using Tools in Chat + +If you want to have a natural back-and-forth chat experience with tools, you can directly integrate tools into +the `chat()` method, instead of using the `generateWithTools()` method. This allows you to register tools that are +automatically used during the conversation between the user and the assistant, creating a more conversational +experience. + +When the model determines that a tool should be used, the tool is automatically executed. The result is then seamlessly +incorporated back into the conversation, enhancing the interaction with real-world data and actions. + +The following example demonstrates usage of a simple tool, registered with the `OllamaAPI`, and then used within a chat +session. The tool invocation and response handling are all managed internally by the API. + + + +::::tip[LLM Response] +> First answer: 6527fb60-9663-4073-b59e-855526e0a0c2 is the ID of the employee named 'Rahul Kumar'. +> +> Second answer: Kumar is the last name of the employee named 'Rahul Kumar'. +:::: + +This tool calling can also be done using the streaming API. + +### Annotation-Based Tool Registration + +Ollama4j provides a declarative and convenient way to define and register tools using Java annotations and reflection. +This approach offers an alternative to the more verbose, explicit tool registration method. + +To use a method as a tool within a chat call, follow these steps: + +* **Annotate the Tool Method:** + * Use the `@ToolSpec` annotation to mark a method as a tool. This annotation describes the tool's purpose. + * Use the `@ToolProperty` annotation to define the input parameters of the tool. The following data types are + currently supported: + * `java.lang.String` + * `java.lang.Integer` + * `java.lang.Boolean` + * `java.math.BigDecimal` +* **Annotate the Ollama Service Class:** + * Annotate the class that interacts with the `OllamaAPI` client using the `@OllamaToolService` annotation. Reference + the provider class(es) containing the `@ToolSpec` annotated methods within this annotation. +* **Register the Annotated Tools:** + * Before making a chat request with the `OllamaAPI`, call the `OllamaAPI.registerAnnotatedTools()` method. This + registers the annotated tools, making them available for use during the chat session. + +Let's try an example. Consider an `OllamaToolService` class that needs to ask the LLM a question that can only be answered by a specific tool. +This tool is implemented within a `GlobalConstantGenerator` class. Following is the code that exposes an annotated method as a tool: + + + +The annotated method can then be used as a tool in the chat session: + + + +Running the above would produce a response similar to: + +::::tip[LLM Response] +> First answer: 0.0000112061 is the most important constant in the world using 10 digits, according to my function. This constant is known as Planck's constant and plays a fundamental role in quantum mechanics. It relates energy and frequency in electromagnetic radiation and action (the product of momentum and distance) for particles. +> +> Second answer: 3-digit constant: 8.001 +:::: diff --git a/docs/docs/apis-generate/chat.md b/docs/docs/apis-generate/chat.md index bf2e1f5..d5a147c 100644 --- a/docs/docs/apis-generate/chat.md +++ b/docs/docs/apis-generate/chat.md @@ -2,267 +2,100 @@ sidebar_position: 7 --- +import CodeEmbed from '@site/src/components/CodeEmbed'; + # Chat This API lets you create a conversation with LLMs. Using this API enables you to ask questions to the model including information using the history of already asked questions and the respective answers. +### Create a new conversation and use chat history to augment follow up questions - -## Create a new conversation and use chat history to augment follow up questions - -```java -import io.github.ollama4j.OllamaAPI; -import io.github.ollama4j.models.chat.OllamaChatMessageRole; -import io.github.ollama4j.models.chat.OllamaChatRequestBuilder; -import io.github.ollama4j.models.chat.OllamaChatRequest; -import io.github.ollama4j.models.chat.OllamaChatResult; -import io.github.ollama4j.types.OllamaModelType; - -public class Main { - - public static void main(String[] args) { - - String host = "http://localhost:11434/"; - - OllamaAPI ollamaAPI = new OllamaAPI(host); - OllamaChatRequestBuilder builder = OllamaChatRequestBuilder.getInstance(OllamaModelType.LLAMA2); - - // create first user question - OllamaChatRequest requestModel = builder.withMessage(OllamaChatMessageRole.USER, "What is the capital of France?") - .build(); - - // start conversation with model - OllamaChatResult chatResult = ollamaAPI.chat(requestModel); - - System.out.println("First answer: " + chatResult.getResponseModel().getMessage().getContent()); - - // create next userQuestion - requestModel = builder.withMessages(chatResult.getChatHistory()).withMessage(OllamaChatMessageRole.USER, "And what is the second largest city?").build(); - - // "continue" conversation with model - chatResult = ollamaAPI.chat(requestModel); - - System.out.println("Second answer: " + chatResult.getResponseModel().getMessage().getContent()); - - System.out.println("Chat History: " + chatResult.getChatHistory()); - } -} - -``` + You will get a response similar to: -> First answer: Should be Paris! +::::tip[LLM Response] + +> First answer: The capital of France is Paris. > -> Second answer: Marseille. +> Second answer: The second-largest city in France is Marseille. > > Chat History: ```json -[ - { - "role": "user", - "content": "What is the capital of France?", - "images": [] - }, - { - "role": "assistant", - "content": "Should be Paris!", - "images": [] - }, - { - "role": "user", - "content": "And what is the second largest city?", - "images": [] - }, - { - "role": "assistant", - "content": "Marseille.", - "images": [] - } -] +[{ + "role" : "user", + "content" : "What is the capital of France?", + "images" : null, + "tool_calls" : [ ] +}, { + "role" : "assistant", + "content" : "The capital of France is Paris.", + "images" : null, + "tool_calls" : null +}, { + "role" : "user", + "content" : "And what is the second largest city?", + "images" : null, + "tool_calls" : [ ] +}, { + "role" : "assistant", + "content" : "The second-largest city in France is Marseille.", + "images" : null, + "tool_calls" : null +}] ``` +:::: -## Conversational loop +### Create a conversation where the answer is streamed -```java -public class Main { - - public static void main(String[] args) { - - OllamaAPI ollamaAPI = new OllamaAPI(); - ollamaAPI.setRequestTimeoutSeconds(60); - - OllamaChatRequestBuilder builder = OllamaChatRequestBuilder.getInstance(""); - - OllamaChatRequest requestModel = builder.withMessage(OllamaChatMessageRole.USER, "").build(); - OllamaChatResult initialChatResult = ollamaAPI.chat(requestModel); - System.out.println(initialChatResult.getResponse()); - - List history = initialChatResult.getChatHistory(); - - while (true) { - OllamaChatResult chatResult = ollamaAPI.chat(builder.withMessages(history).withMessage(OllamaChatMessageRole.USER, ") - OllamaStreamHandler streamHandler = (s) -> { - System.out.println(s); - }; - - OllamaChatResult chatResult = ollamaAPI.chat(requestModel, streamHandler); - } -} -``` - -You will get a response similar to: + +::::tip[LLM Response] +> > The +> > The capital +> > The capital of +> > The capital of France +> > The capital of France is +> > The capital of France is Paris +> > The capital of France is Paris. +> +:::: -## Use a simple Console Output Stream Handler +### Using a simple Console Output Stream Handler -```java -import io.github.ollama4j.OllamaAPI; -import io.github.ollama4j.impl.ConsoleOutputStreamHandler; -import io.github.ollama4j.models.chat.OllamaChatMessageRole; -import io.github.ollama4j.models.chat.OllamaChatRequestBuilder; -import io.github.ollama4j.models.chat.OllamaChatRequest; -import io.github.ollama4j.models.generate.OllamaStreamHandler; -import io.github.ollama4j.types.OllamaModelType; + -public class Main { - public static void main(String[] args) throws Exception { - String host = "http://localhost:11434/"; - OllamaAPI ollamaAPI = new OllamaAPI(host); +### With a Stream Handler to receive the tokens as they are generated - OllamaChatRequestBuilder builder = OllamaChatRequestBuilder.getInstance(OllamaModelType.LLAMA2); - OllamaChatRequest requestModel = builder.withMessage(OllamaChatMessageRole.USER, "List all cricket world cup teams of 2019. Name the teams!") - .build(); - OllamaStreamHandler streamHandler = new ConsoleOutputStreamHandler(); - ollamaAPI.chat(requestModel, streamHandler); - } -} -``` + -## Create a new conversation with individual system prompt +### Create a new conversation with custom system prompt -```java -import io.github.ollama4j.OllamaAPI; -import io.github.ollama4j.models.chat.OllamaChatMessageRole; -import io.github.ollama4j.models.chat.OllamaChatRequestBuilder; -import io.github.ollama4j.models.chat.OllamaChatRequest; -import io.github.ollama4j.models.chat.OllamaChatResult; -import io.github.ollama4j.types.OllamaModelType; + + +You will get a response as: + +::::tip[LLM Response] +> Shhh! +:::: -public class Main { +## Create a conversation about an image (requires a vision model) - public static void main(String[] args) { - - String host = "http://localhost:11434/"; - - OllamaAPI ollamaAPI = new OllamaAPI(host); - OllamaChatRequestBuilder builder = OllamaChatRequestBuilder.getInstance(OllamaModelType.LLAMA2); - - // create request with system-prompt (overriding the model defaults) and user question - OllamaChatRequest requestModel = builder.withMessage(OllamaChatMessageRole.SYSTEM, "You are a silent bot that only says 'NI'. Do not say anything else under any circumstances!") - .withMessage(OllamaChatMessageRole.USER, "What is the capital of France? And what's France's connection with Mona Lisa?") - .build(); - - // start conversation with model - OllamaChatResult chatResult = ollamaAPI.chat(requestModel); - - System.out.println(chatResult.getResponseModel()); - } -} - -``` - -You will get a response similar to: - -> NI. - -## Create a conversation about an image (requires model with image recognition skills) - -```java -import io.github.ollama4j.OllamaAPI; -import io.github.ollama4j.models.chat.OllamaChatMessageRole; -import io.github.ollama4j.models.chat.OllamaChatRequest; -import io.github.ollama4j.models.chat.OllamaChatRequestBuilder; -import io.github.ollama4j.models.chat.OllamaChatResult; -import io.github.ollama4j.types.OllamaModelType; - -import java.io.File; -import java.util.List; - -public class Main { - - public static void main(String[] args) { - - String host = "http://localhost:11434/"; - - OllamaAPI ollamaAPI = new OllamaAPI(host); - OllamaChatRequestBuilder builder = OllamaChatRequestBuilder.getInstance(OllamaModelType.LLAVA); - - // Load Image from File and attach to user message (alternatively images could also be added via URL) - OllamaChatRequest requestModel = - builder.withMessage(OllamaChatMessageRole.USER, "What's in the picture?", - List.of( - new File("/path/to/image"))).build(); - - OllamaChatResult chatResult = ollamaAPI.chat(requestModel); - System.out.println("First answer: " + chatResult.getResponseModel()); - - builder.reset(); - - // Use history to ask further questions about the image or assistant answer - requestModel = - builder.withMessages(chatResult.getChatHistory()) - .withMessage(OllamaChatMessageRole.USER, "What's the dogs breed?").build(); - - chatResult = ollamaAPI.chat(requestModel); - System.out.println("Second answer: " + chatResult.getResponseModel()); - } -} -``` + You will get a response similar to: +::::tip[LLM Response] > First Answer: The image shows a dog sitting on the bow of a boat that is docked in calm water. The boat has two > levels, with the lower level containing seating and what appears to be an engine cover. The dog seems relaxed and > comfortable on the boat, looking out over the water. The background suggests it might be late afternoon or early @@ -272,11 +105,4 @@ You will get a response similar to: > appears to be medium-sized with a short coat and a brown coloration, which might suggest that it is a Golden Retriever > or a similar breed. Without more details like ear shape and tail length, it's not possible to identify the exact breed > confidently. - - -[//]: # (Generated using: https://emgithub.com/) -