forked from Chat_things/NeuroDock
Initial commit
This commit is contained in:
46
.gitignore
vendored
Normal file
46
.gitignore
vendored
Normal file
@@ -0,0 +1,46 @@
|
||||
.gradle
|
||||
build/
|
||||
!gradle/wrapper/gradle-wrapper.jar
|
||||
!**/src/main/**/build/
|
||||
!**/src/test/**/build/
|
||||
|
||||
### IntelliJ IDEA ###
|
||||
.idea/modules.xml
|
||||
.idea/jarRepositories.xml
|
||||
.idea/compiler.xml
|
||||
.idea/libraries/
|
||||
*.iws
|
||||
*.iml
|
||||
*.ipr
|
||||
out/
|
||||
!**/src/main/**/out/
|
||||
!**/src/test/**/out/
|
||||
|
||||
### Eclipse ###
|
||||
.apt_generated
|
||||
.classpath
|
||||
.factorypath
|
||||
.project
|
||||
.settings
|
||||
.springBeans
|
||||
.sts4-cache
|
||||
bin/
|
||||
!**/src/main/**/bin/
|
||||
!**/src/test/**/bin/
|
||||
|
||||
### NetBeans ###
|
||||
/nbproject/private/
|
||||
/nbbuild/
|
||||
/dist/
|
||||
/nbdist/
|
||||
/.nb-gradle/
|
||||
|
||||
### VS Code ###
|
||||
.vscode/
|
||||
|
||||
### Mac OS ###
|
||||
.DS_Store
|
||||
|
||||
/pythonFiles/
|
||||
/messages/
|
||||
/logs/
|
||||
8
.idea/.gitignore
generated
vendored
Normal file
8
.idea/.gitignore
generated
vendored
Normal file
@@ -0,0 +1,8 @@
|
||||
# Default ignored files
|
||||
/shelf/
|
||||
/workspace.xml
|
||||
# Editor-based HTTP Client requests
|
||||
/httpRequests/
|
||||
# Datasource local storage ignored files
|
||||
/dataSources/
|
||||
/dataSources.local.xml
|
||||
17
.idea/gradle.xml
generated
Normal file
17
.idea/gradle.xml
generated
Normal file
@@ -0,0 +1,17 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="GradleMigrationSettings" migrationVersion="1" />
|
||||
<component name="GradleSettings">
|
||||
<option name="linkedExternalProjectsSettings">
|
||||
<GradleProjectSettings>
|
||||
<option name="externalProjectPath" value="$PROJECT_DIR$" />
|
||||
<option name="gradleHome" value="" />
|
||||
<option name="modules">
|
||||
<set>
|
||||
<option value="$PROJECT_DIR$" />
|
||||
</set>
|
||||
</option>
|
||||
</GradleProjectSettings>
|
||||
</option>
|
||||
</component>
|
||||
</project>
|
||||
10
.idea/misc.xml
generated
Normal file
10
.idea/misc.xml
generated
Normal file
@@ -0,0 +1,10 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="ExternalStorageConfigurationManager" enabled="true" />
|
||||
<component name="FrameworkDetectionExcludesConfiguration">
|
||||
<file type="web" url="file://$PROJECT_DIR$" />
|
||||
</component>
|
||||
<component name="ProjectRootManager" version="2" languageLevel="JDK_21" default="true" project-jdk-name="corretto-21" project-jdk-type="JavaSDK">
|
||||
<output url="file://$PROJECT_DIR$/out" />
|
||||
</component>
|
||||
</project>
|
||||
6
.idea/vcs.xml
generated
Normal file
6
.idea/vcs.xml
generated
Normal file
@@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="VcsDirectoryMappings">
|
||||
<mapping directory="$PROJECT_DIR$" vcs="Git" />
|
||||
</component>
|
||||
</project>
|
||||
26
build.gradle
Normal file
26
build.gradle
Normal file
@@ -0,0 +1,26 @@
|
||||
plugins {
|
||||
id 'java'
|
||||
id 'com.gradleup.shadow' version '9.0.0-beta7'
|
||||
}
|
||||
|
||||
group = 'me.zacharias'
|
||||
version = '1.0-SNAPSHOT'
|
||||
|
||||
repositories {
|
||||
mavenCentral()
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation("org.json:json:20250107")
|
||||
implementation("com.github.docker-java:docker-java:3.4.1")
|
||||
}
|
||||
|
||||
test {
|
||||
useJUnitPlatform()
|
||||
}
|
||||
|
||||
jar{
|
||||
manifest {
|
||||
attributes 'Main-Class': 'me.zacharias.chat.Main'
|
||||
}
|
||||
}
|
||||
BIN
gradle/wrapper/gradle-wrapper.jar
vendored
Normal file
BIN
gradle/wrapper/gradle-wrapper.jar
vendored
Normal file
Binary file not shown.
6
gradle/wrapper/gradle-wrapper.properties
vendored
Normal file
6
gradle/wrapper/gradle-wrapper.properties
vendored
Normal file
@@ -0,0 +1,6 @@
|
||||
#Thu Feb 20 00:10:50 CET 2025
|
||||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-8.10-bin.zip
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
zipStorePath=wrapper/dists
|
||||
234
gradlew
vendored
Normal file
234
gradlew
vendored
Normal file
@@ -0,0 +1,234 @@
|
||||
#!/bin/sh
|
||||
|
||||
#
|
||||
# Copyright © 2015-2021 the original authors.
|
||||
#
|
||||
# Licensed 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
|
||||
#
|
||||
# https://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.
|
||||
#
|
||||
|
||||
##############################################################################
|
||||
#
|
||||
# Gradle start up script for POSIX generated by Gradle.
|
||||
#
|
||||
# Important for running:
|
||||
#
|
||||
# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is
|
||||
# noncompliant, but you have some other compliant shell such as ksh or
|
||||
# bash, then to run this script, type that shell name before the whole
|
||||
# command line, like:
|
||||
#
|
||||
# ksh Gradle
|
||||
#
|
||||
# Busybox and similar reduced shells will NOT work, because this script
|
||||
# requires all of these POSIX shell features:
|
||||
# * functions;
|
||||
# * expansions «$var», «${var}», «${var:-default}», «${var+SET}»,
|
||||
# «${var#prefix}», «${var%suffix}», and «$( cmd )»;
|
||||
# * compound commands having a testable exit status, especially «case»;
|
||||
# * various built-in commands including «command», «set», and «ulimit».
|
||||
#
|
||||
# Important for patching:
|
||||
#
|
||||
# (2) This script targets any POSIX shell, so it avoids extensions provided
|
||||
# by Bash, Ksh, etc; in particular arrays are avoided.
|
||||
#
|
||||
# The "traditional" practice of packing multiple parameters into a
|
||||
# space-separated string is a well documented source of bugs and security
|
||||
# problems, so this is (mostly) avoided, by progressively accumulating
|
||||
# options in "$@", and eventually passing that to Java.
|
||||
#
|
||||
# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS,
|
||||
# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly;
|
||||
# see the in-line comments for details.
|
||||
#
|
||||
# There are tweaks for specific operating systems such as AIX, CygWin,
|
||||
# Darwin, MinGW, and NonStop.
|
||||
#
|
||||
# (3) This script is generated from the Groovy template
|
||||
# https://github.com/gradle/gradle/blob/master/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
|
||||
# within the Gradle project.
|
||||
#
|
||||
# You can find Gradle at https://github.com/gradle/gradle/.
|
||||
#
|
||||
##############################################################################
|
||||
|
||||
# Attempt to set APP_HOME
|
||||
|
||||
# Resolve links: $0 may be a link
|
||||
app_path=$0
|
||||
|
||||
# Need this for daisy-chained symlinks.
|
||||
while
|
||||
APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path
|
||||
[ -h "$app_path" ]
|
||||
do
|
||||
ls=$( ls -ld "$app_path" )
|
||||
link=${ls#*' -> '}
|
||||
case $link in #(
|
||||
/*) app_path=$link ;; #(
|
||||
*) app_path=$APP_HOME$link ;;
|
||||
esac
|
||||
done
|
||||
|
||||
APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit
|
||||
|
||||
APP_NAME="Gradle"
|
||||
APP_BASE_NAME=${0##*/}
|
||||
|
||||
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
||||
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
|
||||
|
||||
# Use the maximum available, or set MAX_FD != -1 to use that value.
|
||||
MAX_FD=maximum
|
||||
|
||||
warn () {
|
||||
echo "$*"
|
||||
} >&2
|
||||
|
||||
die () {
|
||||
echo
|
||||
echo "$*"
|
||||
echo
|
||||
exit 1
|
||||
} >&2
|
||||
|
||||
# OS specific support (must be 'true' or 'false').
|
||||
cygwin=false
|
||||
msys=false
|
||||
darwin=false
|
||||
nonstop=false
|
||||
case "$( uname )" in #(
|
||||
CYGWIN* ) cygwin=true ;; #(
|
||||
Darwin* ) darwin=true ;; #(
|
||||
MSYS* | MINGW* ) msys=true ;; #(
|
||||
NONSTOP* ) nonstop=true ;;
|
||||
esac
|
||||
|
||||
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
|
||||
|
||||
|
||||
# Determine the Java command to use to start the JVM.
|
||||
if [ -n "$JAVA_HOME" ] ; then
|
||||
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
|
||||
# IBM's JDK on AIX uses strange locations for the executables
|
||||
JAVACMD=$JAVA_HOME/jre/sh/java
|
||||
else
|
||||
JAVACMD=$JAVA_HOME/bin/java
|
||||
fi
|
||||
if [ ! -x "$JAVACMD" ] ; then
|
||||
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
|
||||
|
||||
Please set the JAVA_HOME variable in your environment to match the
|
||||
location of your Java installation."
|
||||
fi
|
||||
else
|
||||
JAVACMD=java
|
||||
which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
||||
|
||||
Please set the JAVA_HOME variable in your environment to match the
|
||||
location of your Java installation."
|
||||
fi
|
||||
|
||||
# Increase the maximum file descriptors if we can.
|
||||
if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
|
||||
case $MAX_FD in #(
|
||||
max*)
|
||||
MAX_FD=$( ulimit -H -n ) ||
|
||||
warn "Could not query maximum file descriptor limit"
|
||||
esac
|
||||
case $MAX_FD in #(
|
||||
'' | soft) :;; #(
|
||||
*)
|
||||
ulimit -n "$MAX_FD" ||
|
||||
warn "Could not set maximum file descriptor limit to $MAX_FD"
|
||||
esac
|
||||
fi
|
||||
|
||||
# Collect all arguments for the java command, stacking in reverse order:
|
||||
# * args from the command line
|
||||
# * the main class name
|
||||
# * -classpath
|
||||
# * -D...appname settings
|
||||
# * --module-path (only if needed)
|
||||
# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables.
|
||||
|
||||
# For Cygwin or MSYS, switch paths to Windows format before running java
|
||||
if "$cygwin" || "$msys" ; then
|
||||
APP_HOME=$( cygpath --path --mixed "$APP_HOME" )
|
||||
CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" )
|
||||
|
||||
JAVACMD=$( cygpath --unix "$JAVACMD" )
|
||||
|
||||
# Now convert the arguments - kludge to limit ourselves to /bin/sh
|
||||
for arg do
|
||||
if
|
||||
case $arg in #(
|
||||
-*) false ;; # don't mess with options #(
|
||||
/?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath
|
||||
[ -e "$t" ] ;; #(
|
||||
*) false ;;
|
||||
esac
|
||||
then
|
||||
arg=$( cygpath --path --ignore --mixed "$arg" )
|
||||
fi
|
||||
# Roll the args list around exactly as many times as the number of
|
||||
# args, so each arg winds up back in the position where it started, but
|
||||
# possibly modified.
|
||||
#
|
||||
# NB: a `for` loop captures its iteration list before it begins, so
|
||||
# changing the positional parameters here affects neither the number of
|
||||
# iterations, nor the values presented in `arg`.
|
||||
shift # remove old arg
|
||||
set -- "$@" "$arg" # push replacement arg
|
||||
done
|
||||
fi
|
||||
|
||||
# Collect all arguments for the java command;
|
||||
# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of
|
||||
# shell script including quotes and variable substitutions, so put them in
|
||||
# double quotes to make sure that they get re-expanded; and
|
||||
# * put everything else in single quotes, so that it's not re-expanded.
|
||||
|
||||
set -- \
|
||||
"-Dorg.gradle.appname=$APP_BASE_NAME" \
|
||||
-classpath "$CLASSPATH" \
|
||||
org.gradle.wrapper.GradleWrapperMain \
|
||||
"$@"
|
||||
|
||||
# Use "xargs" to parse quoted args.
|
||||
#
|
||||
# With -n1 it outputs one arg per line, with the quotes and backslashes removed.
|
||||
#
|
||||
# In Bash we could simply go:
|
||||
#
|
||||
# readarray ARGS < <( xargs -n1 <<<"$var" ) &&
|
||||
# set -- "${ARGS[@]}" "$@"
|
||||
#
|
||||
# but POSIX shell has neither arrays nor command substitution, so instead we
|
||||
# post-process each arg (as a line of input to sed) to backslash-escape any
|
||||
# character that might be a shell metacharacter, then use eval to reverse
|
||||
# that process (while maintaining the separation between arguments), and wrap
|
||||
# the whole thing up as a single "set" statement.
|
||||
#
|
||||
# This will of course break if any of these variables contains a newline or
|
||||
# an unmatched quote.
|
||||
#
|
||||
|
||||
eval "set -- $(
|
||||
printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" |
|
||||
xargs -n1 |
|
||||
sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' |
|
||||
tr '\n' ' '
|
||||
)" '"$@"'
|
||||
|
||||
exec "$JAVACMD" "$@"
|
||||
89
gradlew.bat
vendored
Normal file
89
gradlew.bat
vendored
Normal file
@@ -0,0 +1,89 @@
|
||||
@rem
|
||||
@rem Copyright 2015 the original author or authors.
|
||||
@rem
|
||||
@rem Licensed under the Apache License, Version 2.0 (the "License");
|
||||
@rem you may not use this file except in compliance with the License.
|
||||
@rem You may obtain a copy of the License at
|
||||
@rem
|
||||
@rem https://www.apache.org/licenses/LICENSE-2.0
|
||||
@rem
|
||||
@rem Unless required by applicable law or agreed to in writing, software
|
||||
@rem distributed under the License is distributed on an "AS IS" BASIS,
|
||||
@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
@rem See the License for the specific language governing permissions and
|
||||
@rem limitations under the License.
|
||||
@rem
|
||||
|
||||
@if "%DEBUG%" == "" @echo off
|
||||
@rem ##########################################################################
|
||||
@rem
|
||||
@rem Gradle startup script for Windows
|
||||
@rem
|
||||
@rem ##########################################################################
|
||||
|
||||
@rem Set local scope for the variables with windows NT shell
|
||||
if "%OS%"=="Windows_NT" setlocal
|
||||
|
||||
set DIRNAME=%~dp0
|
||||
if "%DIRNAME%" == "" set DIRNAME=.
|
||||
set APP_BASE_NAME=%~n0
|
||||
set APP_HOME=%DIRNAME%
|
||||
|
||||
@rem Resolve any "." and ".." in APP_HOME to make it shorter.
|
||||
for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
|
||||
|
||||
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
||||
set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
|
||||
|
||||
@rem Find java.exe
|
||||
if defined JAVA_HOME goto findJavaFromJavaHome
|
||||
|
||||
set JAVA_EXE=java.exe
|
||||
%JAVA_EXE% -version >NUL 2>&1
|
||||
if "%ERRORLEVEL%" == "0" goto execute
|
||||
|
||||
echo.
|
||||
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
||||
echo.
|
||||
echo Please set the JAVA_HOME variable in your environment to match the
|
||||
echo location of your Java installation.
|
||||
|
||||
goto fail
|
||||
|
||||
:findJavaFromJavaHome
|
||||
set JAVA_HOME=%JAVA_HOME:"=%
|
||||
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
|
||||
|
||||
if exist "%JAVA_EXE%" goto execute
|
||||
|
||||
echo.
|
||||
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
|
||||
echo.
|
||||
echo Please set the JAVA_HOME variable in your environment to match the
|
||||
echo location of your Java installation.
|
||||
|
||||
goto fail
|
||||
|
||||
:execute
|
||||
@rem Setup the command line
|
||||
|
||||
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
|
||||
|
||||
|
||||
@rem Execute Gradle
|
||||
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
|
||||
|
||||
:end
|
||||
@rem End local scope for the variables with windows NT shell
|
||||
if "%ERRORLEVEL%"=="0" goto mainEnd
|
||||
|
||||
:fail
|
||||
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
|
||||
rem the _cmd.exe /c_ return code!
|
||||
if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
|
||||
exit /b 1
|
||||
|
||||
:mainEnd
|
||||
if "%OS%"=="Windows_NT" endlocal
|
||||
|
||||
:omega
|
||||
2
settings.gradle
Normal file
2
settings.gradle
Normal file
@@ -0,0 +1,2 @@
|
||||
rootProject.name = 'AI-test'
|
||||
|
||||
320
src/main/java/me/zacharias/chat/Main.java
Normal file
320
src/main/java/me/zacharias/chat/Main.java
Normal file
@@ -0,0 +1,320 @@
|
||||
package me.zacharias.chat;
|
||||
|
||||
import me.zacharias.chat.ollama.*;
|
||||
import me.zacharias.chat.ollama.exceptions.OllamaToolErrorException;
|
||||
import org.json.JSONArray;
|
||||
import org.json.JSONObject;
|
||||
|
||||
import java.io.*;
|
||||
import java.net.*;
|
||||
import java.nio.file.Files;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.ScheduledExecutorService;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
public class Main {
|
||||
private String ollamaIP = "localhost";//"192.168.5.184";
|
||||
private int ollamaPort = 11434;
|
||||
private URL url;
|
||||
|
||||
private static File logFile = new File("./logs/latest.log");
|
||||
private static BufferedWriter logWriter;
|
||||
private ScheduledExecutorService scheduler;
|
||||
|
||||
private OllamaObject ollamaObject;
|
||||
private ArrayList<OllamaFuntionTool> funtionTools;
|
||||
|
||||
{
|
||||
File dir = new File("./logs/");
|
||||
if (!dir.exists()) {
|
||||
dir.mkdir();
|
||||
}
|
||||
dir = new File("./pythonFiles/");
|
||||
if (!dir.exists()) {
|
||||
dir.mkdir();
|
||||
}
|
||||
dir = new File("./messages");
|
||||
if (!dir.exists()) {
|
||||
dir.mkdir();
|
||||
}
|
||||
|
||||
try {
|
||||
url = new URI("http://"+ollamaIP+":"+ollamaPort+"/api/chat").toURL();
|
||||
} catch (MalformedURLException e) {
|
||||
throw new RuntimeException(e);
|
||||
} catch (URISyntaxException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
try {
|
||||
if (logFile.exists()) {
|
||||
BufferedReader br = new BufferedReader(new FileReader(logFile));
|
||||
String line = br.readLine();
|
||||
br.close();
|
||||
if (line != null) {
|
||||
String date = line.substring(0, line.indexOf(">")).replaceAll("[/:]", "-");
|
||||
logFile.renameTo(new File(logFile.getParentFile(), date + ".log"));
|
||||
logFile = new File("./logs/latest.log");
|
||||
}
|
||||
else {
|
||||
System.out.println("Exisitng log file is empty, overwriting it!");
|
||||
logFile.delete();
|
||||
}
|
||||
logFile.createNewFile();
|
||||
}
|
||||
logWriter = new BufferedWriter(new FileWriter(logFile));
|
||||
}catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
|
||||
this.scheduler = Executors.newScheduledThreadPool(1);
|
||||
|
||||
scheduler.scheduleAtFixedRate(() -> {
|
||||
try {
|
||||
logWriter.flush();
|
||||
//System.out.println("Buffer flushed to file.");
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}, 0, 3, TimeUnit.MINUTES);
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
new Main();
|
||||
}
|
||||
|
||||
public Main()
|
||||
{
|
||||
Runtime.getRuntime().addShutdownHook(new Thread(() -> {
|
||||
scheduler.shutdownNow();
|
||||
try {
|
||||
logWriter.flush();
|
||||
logWriter.close();
|
||||
|
||||
LocalDateTime now = LocalDateTime.now();
|
||||
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("HH-mm-ss");
|
||||
|
||||
File messagesFile = new File("./messages/"+now.format(formatter)+".txt");
|
||||
|
||||
BufferedWriter messagesWriter = new BufferedWriter(new FileWriter(messagesFile));
|
||||
|
||||
JSONArray messages = new JSONArray();
|
||||
|
||||
for(OllamaMessage message : ollamaObject.getMessages()) {
|
||||
messages.put(new JSONObject(message.toString()));
|
||||
}
|
||||
|
||||
messagesWriter.write(messages.toString());
|
||||
messagesWriter.close();
|
||||
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}));
|
||||
|
||||
ollamaObject = OllamaObject.builder()
|
||||
.setModel("llama3-AI")
|
||||
.keep_alive(10)
|
||||
.addTool(new TimeTool())
|
||||
.addTool(new PythonRunner())
|
||||
.stream(false)
|
||||
.build();
|
||||
|
||||
writeLog("Creating base OllamaObject with model: "+ollamaObject.getModel());
|
||||
|
||||
funtionTools = new ArrayList<>();
|
||||
|
||||
System.out.println("Installed tools");
|
||||
writeLog("Tools installed in this instance");
|
||||
|
||||
for(OllamaTool tool : ollamaObject.getTools())
|
||||
{
|
||||
if(tool instanceof OllamaFuntionTool funtion)
|
||||
{
|
||||
StringBuilder args = new StringBuilder();
|
||||
OllamaPerameter perameter = funtion.parameters();
|
||||
if(perameter != null) {
|
||||
JSONObject obj = perameter.getProperties();
|
||||
for (String name : obj.keySet()) {
|
||||
args.append(args.toString().isBlank() ? "" : ", ").append(obj.getJSONObject(name).getString("type")).append(Arrays.stream(perameter.getRequired()).anyMatch(str -> str.equalsIgnoreCase(name)) ? "" : "?").append(" ").append(name);
|
||||
}
|
||||
}
|
||||
|
||||
System.out.println("> Function: "+funtion.name()+"("+args+")");
|
||||
writeLog("Function: "+funtion.name()+"("+args+")");
|
||||
funtionTools.add(funtion);
|
||||
}
|
||||
}
|
||||
|
||||
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
|
||||
|
||||
System.out.println("Message Trsnscription:");
|
||||
try {
|
||||
while (true) {
|
||||
System.out.print("> ");
|
||||
StringBuilder message = new StringBuilder(br.readLine());
|
||||
while(br.ready())
|
||||
{
|
||||
message.append("\n").append(br.readLine());
|
||||
}
|
||||
if(message.toString().startsWith("/"))
|
||||
{
|
||||
switch (message.substring(1)) {
|
||||
case "help":
|
||||
System.out.print("""
|
||||
Available commands:
|
||||
/help Prints this help message.
|
||||
/bye Exits the program.
|
||||
/write Flushes the current log stream to file.
|
||||
""");
|
||||
break;
|
||||
case "bye":
|
||||
writeLog("Exiting program...");
|
||||
System.out.println("Bye!");
|
||||
System.exit(0);
|
||||
return;
|
||||
case "write":
|
||||
logWriter.flush();
|
||||
break;
|
||||
default:
|
||||
System.out.println("Unknown command: "+message);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
writeLog("User: "+message);
|
||||
ollamaObject.addMessage(new OllamaMessage(OllamaMessageRole.USER, message.toString()));
|
||||
//System.out.println(ollamaObject.toString());
|
||||
handleResponce(qurryOllama(ollamaObject));
|
||||
}
|
||||
}
|
||||
}catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
System.out.println("Exiting due to exception");
|
||||
System.exit(-1);
|
||||
}
|
||||
}
|
||||
|
||||
public JSONObject qurryOllama(OllamaObject request)
|
||||
{
|
||||
try {
|
||||
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
|
||||
connection.setRequestMethod("POST");
|
||||
connection.setRequestProperty("Content-Type", "application/json");
|
||||
connection.setDoOutput(true);
|
||||
connection.setConnectTimeout(80*1000);
|
||||
|
||||
try(DataOutputStream wr = new DataOutputStream(connection.getOutputStream())) {
|
||||
wr.writeBytes(request.toString());
|
||||
wr.flush();
|
||||
}
|
||||
|
||||
int responseCode = connection.getResponseCode();
|
||||
|
||||
// HTTP_OK or 200 response code generally means that the server ran successfully without any errors
|
||||
StringBuilder response = new StringBuilder();
|
||||
|
||||
// Read response content
|
||||
// connection.getInputStream() purpose is to obtain an input stream for reading the server's response.
|
||||
try (
|
||||
BufferedReader reader = new BufferedReader( new InputStreamReader( connection.getInputStream()))) {
|
||||
String line;
|
||||
while ((line = reader.readLine()) != null) {
|
||||
response.append(line); // Adds every line to response till the end of file.
|
||||
}
|
||||
}
|
||||
|
||||
if (responseCode == HttpURLConnection.HTTP_OK) {
|
||||
|
||||
|
||||
connection.disconnect();
|
||||
return new JSONObject(response.toString());
|
||||
}
|
||||
else {
|
||||
connection.disconnect();
|
||||
System.out.println("Error: HTTP Response code - " + responseCode + "\n"+response.toString());
|
||||
throw new RuntimeException("HTTP Response code - " + responseCode);
|
||||
}
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public void handleResponce(JSONObject responce)
|
||||
{
|
||||
//System.out.println("Responce: "+responce);
|
||||
if(responce != null) {
|
||||
writeLog("Raw responce: "+responce.toString());
|
||||
if(responce.getJSONObject("message").has("tool_calls"))
|
||||
{
|
||||
JSONArray calls = responce.getJSONObject("message").getJSONArray("tool_calls");
|
||||
for(Object call : calls)
|
||||
{
|
||||
if(call instanceof JSONObject jsonObject)
|
||||
{
|
||||
if(jsonObject.has("function"))
|
||||
{
|
||||
JSONObject function = jsonObject.getJSONObject("function");
|
||||
List<OllamaFuntionTool> functions = funtionTools.stream().filter(func -> func.name().equalsIgnoreCase(function.getString("name"))).toList();
|
||||
|
||||
if(functions.isEmpty()) {
|
||||
ollamaObject.addMessage(new OllamaToolError("Function '"+function.getString("name")+"' does not exist"));
|
||||
System.out.println(">> \u001b[31mTried funtion call "+function.getString("name")+" but failed to find it.\u001b[0m");
|
||||
writeLog("Failed function call to "+function.getString("name"));
|
||||
}
|
||||
else {
|
||||
|
||||
OllamaFuntionTool func = functions.getFirst();
|
||||
|
||||
ArrayList<OllamaFunctionArgument> argumentArrayList = new ArrayList<>();
|
||||
|
||||
JSONObject arguments = function.getJSONObject("arguments");
|
||||
|
||||
for (String key : arguments.keySet()) {
|
||||
argumentArrayList.add(new OllamaFunctionArgument(key, arguments.get(key)));
|
||||
}
|
||||
|
||||
try {
|
||||
OllamaToolRespnce function1 = func.function(argumentArrayList.toArray(new OllamaFunctionArgument[0]));
|
||||
ollamaObject.addMessage(function1);
|
||||
System.out.println(">> \u001b[34mCall " + func.name() + "\u001b[0m");
|
||||
writeLog("Successfully function call " + func.name() + " output: " + function1.getResponse());
|
||||
} catch (OllamaToolErrorException e) {
|
||||
ollamaObject.addMessage(new OllamaToolError(e.getMessage()));
|
||||
System.out.println(">> \u001b[31mTried funtion call " + func.name() + " but failed due to " + e.getError() + "\u001b[0m");
|
||||
writeLog(e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if(responce.getJSONObject("message").has("content") && !responce.getJSONObject("message").getString("content").isBlank())
|
||||
{
|
||||
System.out.println(">> \u001b[32m"+responce.getJSONObject("message").getString("content")+"\u001b[0m");
|
||||
writeLog("Response content: "+responce.getJSONObject("message").getString("content"));
|
||||
ollamaObject.addMessage(new OllamaMessage(OllamaMessageRole.ASSISTANT, responce.getJSONObject("message").getString("content")));
|
||||
}
|
||||
handleResponce(qurryOllama(ollamaObject));
|
||||
}
|
||||
else if(responce.getJSONObject("message").has("content") && !responce.getJSONObject("message").getString("content").isBlank())
|
||||
{
|
||||
System.out.println(">> \u001b[32m"+responce.getJSONObject("message").getString("content")+"\u001b[0m");
|
||||
writeLog("Response content: "+responce.getJSONObject("message").getString("content"));
|
||||
ollamaObject.addMessage(new OllamaMessage(OllamaMessageRole.ASSISTANT, responce.getJSONObject("message").getString("content")));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void writeLog(String message)
|
||||
{
|
||||
try {
|
||||
LocalDateTime now = LocalDateTime.now();
|
||||
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("MM/dd%EEEE HH:mm:ss'#'SSS");
|
||||
logWriter.write(now.format(formatter) + "> " + message + "\n");
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
187
src/main/java/me/zacharias/chat/PythonRunner.java
Normal file
187
src/main/java/me/zacharias/chat/PythonRunner.java
Normal file
@@ -0,0 +1,187 @@
|
||||
package me.zacharias.chat;
|
||||
|
||||
import com.github.dockerjava.api.DockerClient;
|
||||
import com.github.dockerjava.api.async.ResultCallback;
|
||||
import com.github.dockerjava.api.async.ResultCallbackTemplate;
|
||||
import com.github.dockerjava.api.command.AttachContainerCmd;
|
||||
import com.github.dockerjava.api.command.LogContainerCmd;
|
||||
import com.github.dockerjava.api.command.StartContainerCmd;
|
||||
import com.github.dockerjava.api.model.Frame;
|
||||
import com.github.dockerjava.core.DefaultDockerClientConfig;
|
||||
import com.github.dockerjava.core.DockerClientBuilder;
|
||||
import com.github.dockerjava.core.DockerClientConfig;
|
||||
import com.github.dockerjava.core.command.LogContainerResultCallback;
|
||||
import me.zacharias.chat.ollama.*;
|
||||
import me.zacharias.chat.ollama.exceptions.OllamaToolErrorException;
|
||||
import org.json.JSONObject;
|
||||
|
||||
import java.io.*;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.security.MessageDigest;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Base64;
|
||||
import java.util.List;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import static me.zacharias.chat.Main.writeLog;
|
||||
|
||||
public class PythonRunner extends OllamaFuntionTool {
|
||||
DockerClient dockerClient;
|
||||
public PythonRunner() {
|
||||
|
||||
DefaultDockerClientConfig.Builder config
|
||||
= DefaultDockerClientConfig.createDefaultConfigBuilder()
|
||||
.withDockerHost("tcp://localhost:2375")
|
||||
.withDockerTlsVerify(false);
|
||||
dockerClient = DockerClientBuilder
|
||||
.getInstance(config)
|
||||
.build();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String name() {
|
||||
return "python_runner";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String description() {
|
||||
return "Runs python code";
|
||||
}
|
||||
|
||||
@Override
|
||||
public OllamaPerameter parameters() {
|
||||
return OllamaPerameter.builder()
|
||||
.addProperty("code", OllamaPerameter.OllamaPerameterBuilder.Type.STRING, "The code to be executed", true)
|
||||
.addProperty("name", OllamaPerameter.OllamaPerameterBuilder.Type.STRING, "The name of the python code")
|
||||
.build();
|
||||
}
|
||||
|
||||
@Override
|
||||
public OllamaToolRespnce function(OllamaFunctionArgument... args) {
|
||||
if(args.length == 0)
|
||||
{
|
||||
throw new OllamaToolErrorException(name(), "Missing code argument");
|
||||
}
|
||||
|
||||
String name = null;
|
||||
String code = null;
|
||||
|
||||
for(OllamaFunctionArgument arg : args)
|
||||
{
|
||||
if(arg.getArgument().equals("name"))
|
||||
{
|
||||
name = (String) arg.getValue();
|
||||
if(!name.endsWith(".py"))
|
||||
{
|
||||
name += ".py";
|
||||
}
|
||||
} else if (arg.getArgument().equals("code")) {
|
||||
code = (String) arg.getValue();
|
||||
}
|
||||
}
|
||||
|
||||
if(name == null)
|
||||
{
|
||||
try {
|
||||
MessageDigest digest = MessageDigest.getInstance("SHA-256");
|
||||
byte[] encodedhash = digest.digest(String.valueOf(args[0].getValue()).getBytes(StandardCharsets.UTF_8));
|
||||
StringBuffer hexString = new StringBuffer();
|
||||
for(byte b : encodedhash)
|
||||
{
|
||||
hexString.append(String.format("%02x", b));
|
||||
}
|
||||
name = hexString.toString()+".py";
|
||||
}catch (Exception e) {}
|
||||
}
|
||||
|
||||
name = name.replace(" ", "_");
|
||||
|
||||
writeLog("Running python code `" + name + "`");
|
||||
|
||||
File pythonFile = new File("./pythonFiles", name);
|
||||
|
||||
if(!pythonFile.exists())
|
||||
{
|
||||
try {
|
||||
BufferedWriter writer = new BufferedWriter(new FileWriter(pythonFile));
|
||||
writer.write(code);
|
||||
writer.close();
|
||||
}catch(IOException e) {}
|
||||
}
|
||||
|
||||
String containerId = dockerClient.createContainerCmd("python").withCmd("python", name).exec().getId();
|
||||
dockerClient.copyArchiveToContainerCmd(containerId)
|
||||
.withHostResource(pythonFile.getPath())
|
||||
//.withRemotePath("~/")
|
||||
.exec();
|
||||
|
||||
dockerClient.startContainerCmd(containerId).exec();
|
||||
|
||||
GetContainerLog log = new GetContainerLog(dockerClient, containerId);
|
||||
|
||||
List<String> logs = new ArrayList<>();
|
||||
|
||||
do {
|
||||
try {
|
||||
Thread.sleep(2000);
|
||||
} catch (InterruptedException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
logs.addAll(log.getDockerLogs());
|
||||
}
|
||||
while (logs.isEmpty());
|
||||
|
||||
StringBuilder output = new StringBuilder();
|
||||
|
||||
for(String s : logs)
|
||||
{
|
||||
output.append(s).append("\n");
|
||||
}
|
||||
|
||||
//writeLog("Result from python: " + output.toString());
|
||||
|
||||
return new OllamaToolRespnce(name(), output.toString());
|
||||
}
|
||||
|
||||
public class GetContainerLog {
|
||||
private DockerClient dockerClient;
|
||||
private String containerId;
|
||||
private int lastLogTime;
|
||||
|
||||
private static String nameOfLogger = "dockertest.PrintContainerLog";
|
||||
private static Logger myLogger = Logger.getLogger(nameOfLogger);
|
||||
|
||||
public GetContainerLog(DockerClient dockerClient, String containerId) {
|
||||
this.dockerClient = dockerClient;
|
||||
this.containerId = containerId;
|
||||
this.lastLogTime = (int) (System.currentTimeMillis() / 1000);
|
||||
}
|
||||
|
||||
public List<String> getDockerLogs() {
|
||||
|
||||
final List<String> logs = new ArrayList<>();
|
||||
|
||||
LogContainerCmd logContainerCmd = dockerClient.logContainerCmd(containerId);
|
||||
logContainerCmd.withStdOut(true).withStdErr(true);
|
||||
logContainerCmd.withSince(lastLogTime); // UNIX timestamp (integer) to filter logs. Specifying a timestamp will only output log-entries since that timestamp.
|
||||
// logContainerCmd.withTail(4); // get only the last 4 log entries
|
||||
|
||||
logContainerCmd.withTimestamps(true);
|
||||
|
||||
try {
|
||||
logContainerCmd.exec(new ResultCallback.Adapter<Frame>() {
|
||||
@Override
|
||||
public void onNext(Frame item) {
|
||||
logs.add(item.toString());
|
||||
}
|
||||
}).awaitCompletion();
|
||||
} catch (InterruptedException e) {
|
||||
myLogger.severe("Interrupted Exception!" + e.getMessage());
|
||||
}
|
||||
|
||||
lastLogTime = (int) (System.currentTimeMillis() / 1000) + 5; // assumes at least a 5 second wait between calls to getDockerLogs
|
||||
|
||||
return logs;
|
||||
}
|
||||
}
|
||||
}
|
||||
32
src/main/java/me/zacharias/chat/TimeTool.java
Normal file
32
src/main/java/me/zacharias/chat/TimeTool.java
Normal file
@@ -0,0 +1,32 @@
|
||||
package me.zacharias.chat;
|
||||
|
||||
import me.zacharias.chat.ollama.OllamaFunctionArgument;
|
||||
import me.zacharias.chat.ollama.OllamaFuntionTool;
|
||||
import me.zacharias.chat.ollama.OllamaPerameter;
|
||||
import me.zacharias.chat.ollama.OllamaToolRespnce;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
public class TimeTool extends OllamaFuntionTool {
|
||||
|
||||
@Override
|
||||
public OllamaToolRespnce function(OllamaFunctionArgument... arguments) {
|
||||
Date date = new Date();
|
||||
return new OllamaToolRespnce(name(), date.toString());
|
||||
}
|
||||
|
||||
@Override
|
||||
public String name() {
|
||||
return "get_current_date";
|
||||
}
|
||||
|
||||
@Override
|
||||
public OllamaPerameter parameters() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String description() {
|
||||
return "Get the current date";
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
package me.zacharias.chat.ollama;
|
||||
|
||||
public class OllamaFunctionArgument {
|
||||
private final String argument;
|
||||
private final Object value;
|
||||
|
||||
public OllamaFunctionArgument(String argument, Object value) {
|
||||
this.argument = argument;
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
public String getArgument() {
|
||||
return argument;
|
||||
}
|
||||
|
||||
public Object getValue() {
|
||||
return value;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
package me.zacharias.chat.ollama;
|
||||
|
||||
import org.json.JSONObject;
|
||||
|
||||
public abstract class OllamaFuntionTool implements OllamaTool {
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
JSONObject ret = new JSONObject();
|
||||
ret.put("tool", "function");
|
||||
|
||||
JSONObject function = new JSONObject();
|
||||
function.put("name", name());
|
||||
function.put("description", description());
|
||||
function.put("parameters", (parameters() == null?
|
||||
new JSONObject() : new JSONObject(parameters().toString())));
|
||||
|
||||
ret.put("function", function);
|
||||
|
||||
return ret.toString();
|
||||
}
|
||||
|
||||
abstract public String name();
|
||||
abstract public String description();
|
||||
abstract public OllamaPerameter parameters();
|
||||
|
||||
abstract public OllamaToolRespnce function(OllamaFunctionArgument... args);
|
||||
}
|
||||
21
src/main/java/me/zacharias/chat/ollama/OllamaMessage.java
Normal file
21
src/main/java/me/zacharias/chat/ollama/OllamaMessage.java
Normal file
@@ -0,0 +1,21 @@
|
||||
package me.zacharias.chat.ollama;
|
||||
|
||||
import org.json.JSONObject;
|
||||
|
||||
public class OllamaMessage {
|
||||
OllamaMessageRole role;
|
||||
String content;
|
||||
|
||||
public OllamaMessage(OllamaMessageRole role, String content) {
|
||||
this.role = role;
|
||||
this.content = content;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
JSONObject json = new JSONObject();
|
||||
json.put("role", role);
|
||||
json.put("content", content);
|
||||
return json.toString();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
package me.zacharias.chat.ollama;
|
||||
|
||||
public enum OllamaMessageRole {
|
||||
USER("user"),
|
||||
ASSISTANT("assistant"),
|
||||
TOOL("tool"),
|
||||
SYSTEM("system");
|
||||
|
||||
private String role;
|
||||
|
||||
OllamaMessageRole(String role) {
|
||||
this.role = role;
|
||||
}
|
||||
|
||||
public String getRole() {
|
||||
return role;
|
||||
}
|
||||
}
|
||||
166
src/main/java/me/zacharias/chat/ollama/OllamaObject.java
Normal file
166
src/main/java/me/zacharias/chat/ollama/OllamaObject.java
Normal file
@@ -0,0 +1,166 @@
|
||||
package me.zacharias.chat.ollama;
|
||||
|
||||
import org.json.JSONArray;
|
||||
import org.json.JSONObject;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public class OllamaObject {
|
||||
String model;
|
||||
ArrayList<OllamaMessage> messages;
|
||||
OllamaTool[] tools;
|
||||
JSONObject format;
|
||||
Map<String, Object> options;
|
||||
boolean stream;
|
||||
String keep_alive;
|
||||
|
||||
private OllamaObject(String model, ArrayList<OllamaMessage> messages, OllamaTool[] tools, JSONObject format, Map<String, Object> options, boolean stream, String keep_alive) {
|
||||
this.model = model;
|
||||
this.messages = messages;
|
||||
this.tools = tools;
|
||||
this.format = format;
|
||||
this.options = options;
|
||||
this.stream = stream;
|
||||
this.keep_alive = keep_alive;
|
||||
}
|
||||
|
||||
public String getModel() {
|
||||
return model;
|
||||
}
|
||||
|
||||
public ArrayList<OllamaMessage> getMessages() {
|
||||
return messages;
|
||||
}
|
||||
|
||||
public OllamaTool[] getTools() {
|
||||
return tools;
|
||||
}
|
||||
|
||||
public JSONObject getFormat() {
|
||||
return format;
|
||||
}
|
||||
|
||||
public Map<String, Object> getOptions() {
|
||||
return options;
|
||||
}
|
||||
|
||||
public boolean isStream() {
|
||||
return stream;
|
||||
}
|
||||
|
||||
public String getKeep_alive() {
|
||||
return keep_alive;
|
||||
}
|
||||
|
||||
public void addMessage(OllamaMessage message) {
|
||||
messages.add(message);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
JSONObject json = new JSONObject();
|
||||
|
||||
JSONArray tools = new JSONArray();
|
||||
for (OllamaTool tool : this.tools) {
|
||||
tools.put(new JSONObject(tool.toString()));
|
||||
}
|
||||
|
||||
JSONArray messages = new JSONArray();
|
||||
for (OllamaMessage message : this.messages) {
|
||||
messages.put(new JSONObject(message.toString()));
|
||||
}
|
||||
|
||||
json.put("model", model);
|
||||
json.put("messages", messages);
|
||||
json.put("tools", tools);
|
||||
json.put("format", format);
|
||||
json.put("options", options);
|
||||
json.put("stream", stream);
|
||||
json.put("keep_alive", keep_alive);
|
||||
return json.toString();
|
||||
}
|
||||
|
||||
public static OllamaObjectBuilder builder()
|
||||
{
|
||||
return new OllamaObjectBuilder();
|
||||
}
|
||||
|
||||
public static class OllamaObjectBuilder {
|
||||
String model;
|
||||
ArrayList<OllamaMessage> messages = new ArrayList<>();
|
||||
ArrayList<OllamaTool> tools = new ArrayList<>();
|
||||
JSONObject format;
|
||||
Map<String, Object> options = new HashMap<>();
|
||||
boolean stream;
|
||||
String keep_alive;
|
||||
|
||||
public OllamaObjectBuilder() {}
|
||||
|
||||
public OllamaObjectBuilder format(String format) {
|
||||
this.format = new JSONObject(format);
|
||||
return this;
|
||||
}
|
||||
|
||||
public OllamaObjectBuilder options(Map<String, Object> options) {
|
||||
this.options.putAll(options);
|
||||
return this;
|
||||
}
|
||||
|
||||
public OllamaObjectBuilder option(String key, String value) {
|
||||
this.options.put(key, value);
|
||||
return this;
|
||||
}
|
||||
|
||||
public OllamaObjectBuilder stream(boolean stream) {
|
||||
this.stream = stream;
|
||||
return this;
|
||||
}
|
||||
|
||||
public OllamaObjectBuilder keep_alive(String keep_alive) {
|
||||
this.keep_alive = keep_alive;
|
||||
return this;
|
||||
}
|
||||
|
||||
public OllamaObjectBuilder keep_alive(int minutes) {
|
||||
this.keep_alive = minutes+"m";
|
||||
return this;
|
||||
}
|
||||
|
||||
public OllamaObjectBuilder addTool(OllamaTool tools) {
|
||||
this.tools.add(tools);
|
||||
return this;
|
||||
}
|
||||
|
||||
public OllamaObjectBuilder addTools(ArrayList<? extends OllamaTool> tools) {
|
||||
this.tools.addAll(tools);
|
||||
return this;
|
||||
}
|
||||
|
||||
public OllamaObjectBuilder addTools(OllamaTool... tools) {
|
||||
this.tools.addAll(List.of(tools));
|
||||
return this;
|
||||
}
|
||||
|
||||
public OllamaObjectBuilder addMessages(OllamaMessage... messages) {
|
||||
this.messages.addAll(List.of(messages));
|
||||
return this;
|
||||
}
|
||||
|
||||
public OllamaObjectBuilder addMessage(OllamaMessage messages) {
|
||||
this.messages.add(messages);
|
||||
return this;
|
||||
}
|
||||
|
||||
public OllamaObjectBuilder setModel(String model) {
|
||||
this.model = model;
|
||||
return this;
|
||||
}
|
||||
|
||||
public OllamaObject build() {
|
||||
return new OllamaObject(model, messages, tools.toArray(new OllamaTool[0]), format, options, stream, keep_alive);
|
||||
}
|
||||
}
|
||||
}
|
||||
116
src/main/java/me/zacharias/chat/ollama/OllamaPerameter.java
Normal file
116
src/main/java/me/zacharias/chat/ollama/OllamaPerameter.java
Normal file
@@ -0,0 +1,116 @@
|
||||
package me.zacharias.chat.ollama;
|
||||
|
||||
import org.json.JSONObject;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
public class OllamaPerameter {
|
||||
|
||||
private OllamaPerameter(JSONObject properties, String[] required) {
|
||||
this.properties = properties;
|
||||
this.required = required;
|
||||
};
|
||||
@Override
|
||||
public String toString() {
|
||||
JSONObject json = new JSONObject();
|
||||
|
||||
json.put("type", "object");
|
||||
json.put("properties", properties);
|
||||
json.put("required", required);
|
||||
|
||||
return json.toString();
|
||||
}
|
||||
|
||||
JSONObject properties;
|
||||
String[] required;
|
||||
|
||||
public JSONObject getProperties() {
|
||||
return properties;
|
||||
}
|
||||
|
||||
public String[] getRequired() {
|
||||
return required;
|
||||
}
|
||||
|
||||
public static OllamaPerameterBuilder builder() {
|
||||
return new OllamaPerameterBuilder();
|
||||
}
|
||||
|
||||
public static class OllamaPerameterBuilder {
|
||||
Map<String, Property> propertyMap = new HashMap<>();
|
||||
ArrayList<String> required = new ArrayList<>();
|
||||
|
||||
public OllamaPerameterBuilder addProperty(String name, Type type, String description) {
|
||||
if(name == null || type == null || description == null) {
|
||||
return this;
|
||||
}
|
||||
propertyMap.put(name, new Property(type.getType(), description));
|
||||
return this;
|
||||
}
|
||||
|
||||
public OllamaPerameterBuilder addProperty(String name, Type type, String description, boolean required) {
|
||||
if(name == null || type == null || description == null) {
|
||||
return this;
|
||||
}
|
||||
propertyMap.put(name, new Property(type.getType(), description));
|
||||
this.required.add(name);
|
||||
return this;
|
||||
}
|
||||
|
||||
public OllamaPerameterBuilder required(String name) {
|
||||
required.add(name);
|
||||
return this;
|
||||
}
|
||||
|
||||
public OllamaPerameterBuilder removeProperty(String name) {
|
||||
propertyMap.remove(name);
|
||||
return this;
|
||||
}
|
||||
|
||||
public OllamaPerameter build() {
|
||||
JSONObject properties = new JSONObject();
|
||||
for(String name : propertyMap.keySet()) {
|
||||
properties.put(name, new JSONObject(propertyMap.get(name).toString()));
|
||||
}
|
||||
return new OllamaPerameter(properties, required.toArray(new String[0]));
|
||||
}
|
||||
|
||||
private class Property {
|
||||
String type;
|
||||
String description;
|
||||
|
||||
public Property(String type, String description) {
|
||||
this.type = type;
|
||||
this.description = description;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
JSONObject json = new JSONObject();
|
||||
|
||||
json.put("type", type);
|
||||
json.put("description", description);
|
||||
|
||||
return json.toString();
|
||||
}
|
||||
}
|
||||
|
||||
public enum Type {
|
||||
STRING("string"),
|
||||
INT("int"),
|
||||
BOOLEAN("boolean");
|
||||
|
||||
private String type;
|
||||
|
||||
public String getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
Type(String type) {
|
||||
this.type = type;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
5
src/main/java/me/zacharias/chat/ollama/OllamaTool.java
Normal file
5
src/main/java/me/zacharias/chat/ollama/OllamaTool.java
Normal file
@@ -0,0 +1,5 @@
|
||||
package me.zacharias.chat.ollama;
|
||||
|
||||
|
||||
public interface OllamaTool {
|
||||
}
|
||||
15
src/main/java/me/zacharias/chat/ollama/OllamaToolError.java
Normal file
15
src/main/java/me/zacharias/chat/ollama/OllamaToolError.java
Normal file
@@ -0,0 +1,15 @@
|
||||
package me.zacharias.chat.ollama;
|
||||
|
||||
import org.json.JSONObject;
|
||||
|
||||
public class OllamaToolError extends OllamaMessage {
|
||||
String error;
|
||||
public OllamaToolError(String error) {
|
||||
super(OllamaMessageRole.TOOL, new JSONObject().put("error", error).toString());
|
||||
this.error = error;
|
||||
}
|
||||
|
||||
public String getError() {
|
||||
return error;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
package me.zacharias.chat.ollama;
|
||||
|
||||
import org.json.JSONObject;
|
||||
|
||||
public class OllamaToolRespnce extends OllamaMessage {
|
||||
private final String tool;
|
||||
private final String response;
|
||||
public OllamaToolRespnce(String tool, String response) {
|
||||
super(OllamaMessageRole.TOOL, new JSONObject().put("tool", tool).put("result", response).toString());
|
||||
this.tool = tool;
|
||||
this.response = response;
|
||||
}
|
||||
|
||||
public String getTool() {
|
||||
return tool;
|
||||
}
|
||||
|
||||
public String getResponse() {
|
||||
return response;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
package me.zacharias.chat.ollama.exceptions;
|
||||
|
||||
import me.zacharias.chat.ollama.OllamaToolRespnce;
|
||||
|
||||
public class OllamaToolErrorException extends RuntimeException {
|
||||
private final String tool;
|
||||
private final String error;
|
||||
public OllamaToolErrorException(String tool, String error) {
|
||||
super(tool + ": " + error);
|
||||
this.tool = tool;
|
||||
this.error = error;
|
||||
}
|
||||
|
||||
public String getTool() {
|
||||
return tool;
|
||||
}
|
||||
|
||||
public String getError() {
|
||||
return error;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user