mirror of
https://github.com/amithkoujalgi/ollama4j.git
synced 2025-10-13 17:08:57 +02:00
Add default target to Makefile, enhance Ollama class to use tools, and introduce Agent and SampleAgent classes for interactive tool usage. Update Javadoc generation message and improve error handling in endpoint callers.
This commit is contained in:
parent
64c629775a
commit
da6d20d118
6
Makefile
6
Makefile
@ -1,3 +1,7 @@
|
||||
# Default target
|
||||
.PHONY: all
|
||||
all: dev build
|
||||
|
||||
dev:
|
||||
@echo "Setting up dev environment..."
|
||||
@command -v pre-commit >/dev/null 2>&1 || { echo "Error: pre-commit is not installed. Please install it first."; exit 1; }
|
||||
@ -43,7 +47,7 @@ doxygen:
|
||||
@doxygen Doxyfile
|
||||
|
||||
javadoc:
|
||||
@echo "\033[0;34mGenerating Javadocs into '$(javadocfolder)'...\033[0m"
|
||||
@echo "\033[0;34mGenerating Javadocs...\033[0m"
|
||||
@mvn clean javadoc:javadoc
|
||||
@if [ -f "target/reports/apidocs/index.html" ]; then \
|
||||
echo "\033[0;32mJavadocs generated in target/reports/apidocs/index.html\033[0m"; \
|
||||
|
@ -805,6 +805,7 @@ public class Ollama {
|
||||
chatRequest.setMessages(msgs);
|
||||
msgs.add(ocm);
|
||||
OllamaChatTokenHandler hdlr = null;
|
||||
chatRequest.setUseTools(true);
|
||||
chatRequest.setTools(request.getTools());
|
||||
if (streamObserver != null) {
|
||||
chatRequest.setStream(true);
|
||||
@ -881,7 +882,7 @@ public class Ollama {
|
||||
// only add tools if tools flag is set
|
||||
if (request.isUseTools()) {
|
||||
// add all registered tools to request
|
||||
request.setTools(toolRegistry.getRegisteredTools());
|
||||
request.getTools().addAll(toolRegistry.getRegisteredTools());
|
||||
}
|
||||
|
||||
if (tokenHandler != null) {
|
||||
|
93
src/main/java/io/github/ollama4j/agent/Agent.java
Normal file
93
src/main/java/io/github/ollama4j/agent/Agent.java
Normal file
@ -0,0 +1,93 @@
|
||||
/*
|
||||
* Ollama4j - Java library for interacting with Ollama server.
|
||||
* Copyright (c) 2025 Amith Koujalgi and contributors.
|
||||
*
|
||||
* Licensed under the MIT License (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
*
|
||||
*/
|
||||
package io.github.ollama4j.agent;
|
||||
|
||||
import io.github.ollama4j.Ollama;
|
||||
import io.github.ollama4j.exceptions.OllamaException;
|
||||
import io.github.ollama4j.impl.ConsoleOutputGenerateTokenHandler;
|
||||
import io.github.ollama4j.models.chat.*;
|
||||
import io.github.ollama4j.tools.Tools;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Scanner;
|
||||
|
||||
public class Agent {
|
||||
private final String name;
|
||||
private final List<Tools.Tool> tools;
|
||||
private final Ollama ollamaClient;
|
||||
private final String model;
|
||||
private final List<OllamaChatMessage> chatHistory;
|
||||
|
||||
public Agent(String name, Ollama ollamaClient, String model, List<Tools.Tool> tools) {
|
||||
this.name = name;
|
||||
this.ollamaClient = ollamaClient;
|
||||
this.chatHistory = new ArrayList<>();
|
||||
this.tools = tools;
|
||||
this.model = model;
|
||||
}
|
||||
|
||||
public String think(String userInput) throws OllamaException {
|
||||
StringBuilder availableToolsDescription = new StringBuilder();
|
||||
if (!tools.isEmpty()) {
|
||||
for (Tools.Tool t : tools) {
|
||||
String toolName = t.getToolSpec().getName();
|
||||
String toolDescription = t.getToolSpec().getDescription();
|
||||
availableToolsDescription.append(
|
||||
"\nTool name: '"
|
||||
+ toolName
|
||||
+ "'. Tool Description: '"
|
||||
+ toolDescription
|
||||
+ "'.\n");
|
||||
}
|
||||
}
|
||||
if (chatHistory.isEmpty()) {
|
||||
chatHistory.add(
|
||||
new OllamaChatMessage(
|
||||
OllamaChatMessageRole.SYSTEM,
|
||||
"You are a helpful assistant named "
|
||||
+ name
|
||||
+ ". You only perform tasks using tools available for you. You"
|
||||
+ " respond very precisely and you don't overthink or be too"
|
||||
+ " creative. Do not ever reveal the tool specification in"
|
||||
+ " terms of code or JSON or in a way that a software engineer"
|
||||
+ " sees it. Just be careful with your responses and respond"
|
||||
+ " like a human. Note that you only execute tools provided to"
|
||||
+ " you. Following are the tools that you have access to and"
|
||||
+ " you can perform right actions using right tools."
|
||||
+ availableToolsDescription));
|
||||
}
|
||||
OllamaChatRequest request =
|
||||
OllamaChatRequest.builder()
|
||||
.withTools(tools)
|
||||
.withUseTools(true)
|
||||
.withModel(model)
|
||||
.withMessages(chatHistory)
|
||||
.withMessage(OllamaChatMessageRole.USER, userInput)
|
||||
.build();
|
||||
request.withMessage(OllamaChatMessageRole.USER, userInput);
|
||||
OllamaChatStreamObserver chatTokenHandler =
|
||||
new OllamaChatStreamObserver(
|
||||
new ConsoleOutputGenerateTokenHandler(),
|
||||
new ConsoleOutputGenerateTokenHandler());
|
||||
OllamaChatResult response = ollamaClient.chat(request, chatTokenHandler);
|
||||
chatHistory.clear();
|
||||
chatHistory.addAll(response.getChatHistory());
|
||||
return response.getResponseModel().getMessage().getResponse();
|
||||
}
|
||||
|
||||
public void runInteractive() throws OllamaException {
|
||||
Scanner sc = new Scanner(System.in);
|
||||
while (true) {
|
||||
System.out.print("\nYou: ");
|
||||
String input = sc.nextLine();
|
||||
if ("exit".equalsIgnoreCase(input)) break;
|
||||
String response = this.think(input);
|
||||
}
|
||||
}
|
||||
}
|
215
src/main/java/io/github/ollama4j/agent/SampleAgent.java
Normal file
215
src/main/java/io/github/ollama4j/agent/SampleAgent.java
Normal file
@ -0,0 +1,215 @@
|
||||
/*
|
||||
* Ollama4j - Java library for interacting with Ollama server.
|
||||
* Copyright (c) 2025 Amith Koujalgi and contributors.
|
||||
*
|
||||
* Licensed under the MIT License (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
*
|
||||
*/
|
||||
package io.github.ollama4j.agent;
|
||||
|
||||
import io.github.ollama4j.Ollama;
|
||||
import io.github.ollama4j.exceptions.OllamaException;
|
||||
import io.github.ollama4j.tools.ToolFunction;
|
||||
import io.github.ollama4j.tools.Tools;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public class SampleAgent {
|
||||
public static void main(String[] args) throws OllamaException {
|
||||
Ollama ollama = new Ollama("http://192.168.29.224:11434");
|
||||
ollama.setRequestTimeoutSeconds(120);
|
||||
String model = "mistral:7b";
|
||||
ollama.pullModel(model);
|
||||
|
||||
List<Tools.Tool> tools = new ArrayList<>();
|
||||
// Weather tool
|
||||
tools.add(
|
||||
Tools.Tool.builder()
|
||||
.toolSpec(
|
||||
Tools.ToolSpec.builder()
|
||||
.name("weather-tool")
|
||||
.description(
|
||||
"Gets current weather for a given location and a"
|
||||
+ " given day")
|
||||
.parameters(
|
||||
Tools.Parameters.of(
|
||||
Map.of(
|
||||
"location",
|
||||
Tools.Property.builder()
|
||||
.type("string")
|
||||
.description(
|
||||
"The location to"
|
||||
+ " get the"
|
||||
+ " weather"
|
||||
+ " for.")
|
||||
.required(true)
|
||||
.build(),
|
||||
"day",
|
||||
Tools.Property.builder()
|
||||
.type("string")
|
||||
.description(
|
||||
"The day of the"
|
||||
+ " week to get"
|
||||
+ " the weather"
|
||||
+ " for.")
|
||||
.required(true)
|
||||
.build())))
|
||||
.build())
|
||||
.toolFunction(new WeatherToolFunction())
|
||||
.build());
|
||||
|
||||
// Calculator tool
|
||||
tools.add(
|
||||
Tools.Tool.builder()
|
||||
.toolSpec(
|
||||
Tools.ToolSpec.builder()
|
||||
.name("calculator-tool")
|
||||
.description(
|
||||
"Performs a simple arithmetic operation between two"
|
||||
+ " numbers")
|
||||
.parameters(
|
||||
Tools.Parameters.of(
|
||||
Map.of(
|
||||
"operation",
|
||||
Tools.Property.builder()
|
||||
.type("string")
|
||||
.description(
|
||||
"Arithmetic"
|
||||
+ " operation"
|
||||
+ " to perform:"
|
||||
+ " add,"
|
||||
+ " subtract,"
|
||||
+ " multiply,"
|
||||
+ " divide")
|
||||
.required(true)
|
||||
.build(),
|
||||
"a",
|
||||
Tools.Property.builder()
|
||||
.type("number")
|
||||
.description(
|
||||
"The first operand")
|
||||
.required(true)
|
||||
.build(),
|
||||
"b",
|
||||
Tools.Property.builder()
|
||||
.type("number")
|
||||
.description(
|
||||
"The second"
|
||||
+ " operand")
|
||||
.required(true)
|
||||
.build())))
|
||||
.build())
|
||||
.toolFunction(new CalculatorToolFunction())
|
||||
.build());
|
||||
|
||||
// Hotel Booking tool (dummy)
|
||||
tools.add(
|
||||
Tools.Tool.builder()
|
||||
.toolSpec(
|
||||
Tools.ToolSpec.builder()
|
||||
.name("hotel-booking-tool")
|
||||
.description(
|
||||
"Helps with booking a hotel room in a specified"
|
||||
+ " city for given dates and number of guests.")
|
||||
.parameters(
|
||||
Tools.Parameters.of(
|
||||
Map.of(
|
||||
"city",
|
||||
Tools.Property.builder()
|
||||
.type("string")
|
||||
.description(
|
||||
"The city where you"
|
||||
+ " want to"
|
||||
+ " book the"
|
||||
+ " hotel.")
|
||||
.required(true)
|
||||
.build(),
|
||||
"checkin_date",
|
||||
Tools.Property.builder()
|
||||
.type("string")
|
||||
.description(
|
||||
"Check-in date.")
|
||||
.required(true)
|
||||
.build(),
|
||||
"checkout_date",
|
||||
Tools.Property.builder()
|
||||
.type("string")
|
||||
.description(
|
||||
"Check-out date.")
|
||||
.required(true)
|
||||
.build(),
|
||||
"guests",
|
||||
Tools.Property.builder()
|
||||
.type("number")
|
||||
.description(
|
||||
"Number of guests.")
|
||||
.required(true)
|
||||
.build())))
|
||||
.build())
|
||||
.toolFunction(new HotelBookingToolFunction())
|
||||
.build());
|
||||
|
||||
Agent agent = new Agent("Nimma Mirta", ollama, model, tools);
|
||||
agent.runInteractive();
|
||||
}
|
||||
}
|
||||
|
||||
/** ToolFunction implementation for diff checking. */
|
||||
class WeatherToolFunction implements ToolFunction {
|
||||
@Override
|
||||
public Object apply(Map<String, Object> arguments) {
|
||||
String response =
|
||||
"Monday: pleasant, Tuesday: Sunny, Wednesday: Windy, Thursday: Cloudy, Friday:"
|
||||
+ " Rainy, Saturday: Heavy rains, Sunday: Clear";
|
||||
return response;
|
||||
}
|
||||
}
|
||||
|
||||
/** ToolFunction implementation for simple calculations. */
|
||||
class CalculatorToolFunction implements ToolFunction {
|
||||
@Override
|
||||
public Object apply(Map<String, Object> arguments) {
|
||||
String operation = (String) arguments.get("operation");
|
||||
double a = ((Number) arguments.get("a")).doubleValue();
|
||||
double b = ((Number) arguments.get("b")).doubleValue();
|
||||
double result;
|
||||
switch (operation.toLowerCase()) {
|
||||
case "add":
|
||||
result = a + b;
|
||||
break;
|
||||
case "subtract":
|
||||
result = a - b;
|
||||
break;
|
||||
case "multiply":
|
||||
result = a * b;
|
||||
break;
|
||||
case "divide":
|
||||
if (b == 0) {
|
||||
return "Cannot divide by zero.";
|
||||
}
|
||||
result = a / b;
|
||||
break;
|
||||
default:
|
||||
return "Unknown operation: " + operation;
|
||||
}
|
||||
return "Result: " + result;
|
||||
}
|
||||
}
|
||||
|
||||
/** ToolFunction implementation for a dummy hotel booking agent. */
|
||||
class HotelBookingToolFunction implements ToolFunction {
|
||||
@Override
|
||||
public Object apply(Map<String, Object> arguments) {
|
||||
String city = (String) arguments.get("city");
|
||||
String checkin = (String) arguments.get("checkin_date");
|
||||
String checkout = (String) arguments.get("checkout_date");
|
||||
int guests = ((Number) arguments.get("guests")).intValue();
|
||||
|
||||
// Dummy booking confirmation logic
|
||||
return String.format(
|
||||
"Booking confirmed! %d guest(s) in %s from %s to %s. (Confirmation #DUMMY1234)",
|
||||
guests, city, checkin, checkout);
|
||||
}
|
||||
}
|
@ -141,7 +141,6 @@ public class OllamaChatEndpointCaller extends OllamaEndpointCaller {
|
||||
responseBuffer);
|
||||
if (statusCode != 200) {
|
||||
LOG.error("Status code: {}", statusCode);
|
||||
System.out.println(responseBuffer);
|
||||
throw new OllamaException(responseBuffer.toString());
|
||||
}
|
||||
if (wantedToolsForStream != null && ollamaChatResponseModel != null) {
|
||||
|
@ -136,18 +136,21 @@ public class OllamaGenerateEndpointCaller extends OllamaEndpointCaller {
|
||||
thinkingBuffer.toString(),
|
||||
endTime - startTime,
|
||||
statusCode);
|
||||
ollamaResult.setModel(ollamaGenerateResponseModel.getModel());
|
||||
ollamaResult.setCreatedAt(ollamaGenerateResponseModel.getCreatedAt());
|
||||
ollamaResult.setDone(ollamaGenerateResponseModel.isDone());
|
||||
ollamaResult.setDoneReason(ollamaGenerateResponseModel.getDoneReason());
|
||||
ollamaResult.setContext(ollamaGenerateResponseModel.getContext());
|
||||
ollamaResult.setTotalDuration(ollamaGenerateResponseModel.getTotalDuration());
|
||||
ollamaResult.setLoadDuration(ollamaGenerateResponseModel.getLoadDuration());
|
||||
ollamaResult.setPromptEvalCount(ollamaGenerateResponseModel.getPromptEvalCount());
|
||||
ollamaResult.setPromptEvalDuration(ollamaGenerateResponseModel.getPromptEvalDuration());
|
||||
ollamaResult.setEvalCount(ollamaGenerateResponseModel.getEvalCount());
|
||||
ollamaResult.setEvalDuration(ollamaGenerateResponseModel.getEvalDuration());
|
||||
|
||||
if (ollamaGenerateResponseModel != null) {
|
||||
ollamaResult.setModel(ollamaGenerateResponseModel.getModel());
|
||||
ollamaResult.setCreatedAt(ollamaGenerateResponseModel.getCreatedAt());
|
||||
ollamaResult.setDone(ollamaGenerateResponseModel.isDone());
|
||||
ollamaResult.setDoneReason(ollamaGenerateResponseModel.getDoneReason());
|
||||
ollamaResult.setContext(ollamaGenerateResponseModel.getContext());
|
||||
ollamaResult.setTotalDuration(ollamaGenerateResponseModel.getTotalDuration());
|
||||
ollamaResult.setLoadDuration(ollamaGenerateResponseModel.getLoadDuration());
|
||||
ollamaResult.setPromptEvalCount(ollamaGenerateResponseModel.getPromptEvalCount());
|
||||
ollamaResult.setPromptEvalDuration(
|
||||
ollamaGenerateResponseModel.getPromptEvalDuration());
|
||||
ollamaResult.setEvalCount(ollamaGenerateResponseModel.getEvalCount());
|
||||
ollamaResult.setEvalDuration(ollamaGenerateResponseModel.getEvalDuration());
|
||||
}
|
||||
LOG.debug("Model plain response: {}", ollamaGenerateResponseModel);
|
||||
LOG.debug("Model response: {}", ollamaResult);
|
||||
return ollamaResult;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user