001/*
002 * SPDX-License-Identifier: Apache-2.0
003 *
004 * Copyright 2024-2026 The Enola <https://enola.dev> Authors
005 *
006 * Licensed under the Apache License, Version 2.0 (the "License");
007 * you may not use this file except in compliance with the License.
008 * You may obtain a copy of the License at
009 *
010 *     https://www.apache.org/licenses/LICENSE-2.0
011 *
012 * Unless required by applicable law or agreed to in writing, software
013 * distributed under the License is distributed on an "AS IS" BASIS,
014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
015 * See the License for the specific language governing permissions and
016 * limitations under the License.
017 */
018package dev.enola.ai.ollama;
019
020import static dev.enola.common.function.MoreStreams.forEach;
021
022import dev.enola.common.io.resource.ResourceProviders;
023import dev.enola.common.io.resource.stream.GlobResolver;
024import dev.enola.common.io.resource.stream.GlobResolvers;
025
026import io.github.ollama4j.OllamaAPI;
027import io.github.ollama4j.exceptions.OllamaBaseException;
028import io.github.ollama4j.utils.OptionsBuilder;
029
030import java.io.IOException;
031import java.net.URISyntaxException;
032
033public class OllamaMain {
034
035    // See https://github.com/vorburger/vorburger.ch-Notes/blob/develop/ml/ollama1.md
036
037    public static void main(String[] args)
038            throws IOException, OllamaBaseException, URISyntaxException, InterruptedException {
039        // This won't work, because it's too big:
040        // args = new String[]
041        // {"file:/home/vorburger/git/github.com/enola-dev/enola/java/**.java?charset=UTF-8",
042        // "What's this code all about?"};
043        // ...
044        // But e.g. "file:$PWD/java/dev/enola/common/function/**.java?charset=UTF-8" kinda works!
045
046        if (args.length != 2) {
047            System.err.println("Usage: java OllamaMain <path-to-directory-of-code> <prompt>");
048            System.exit(1);
049        }
050
051        var context = suckFiles(args[0]);
052        var prompt = args[1];
053
054        var modelName = "codegemma:7b";
055        var baseURL = "http://localhost:11434/";
056        var options = new OptionsBuilder().setSeed(1).build();
057
058        OllamaAPI ollamaAPI = new OllamaAPI(baseURL);
059        ollamaAPI.setRequestTimeoutSeconds(30);
060        ollamaAPI.ping();
061        // System.out.println(ollamaAPI.getModelDetails(modelName));
062
063        System.out.println("Context Size is: " + context.length());
064        System.out.println(
065                ollamaAPI
066                        .generate(
067                                modelName,
068                                "Here is a lot of source code: "
069                                        + context
070                                        + "\n"
071                                        + "Now please answer the following question about this"
072                                        + " code, and avoid repeating yourself: "
073                                        + prompt,
074                                // "Do not provide any reasoning, just answer the question",
075                                true,
076                                options)
077                        .getResponse());
078        System.out.println("Context Size was: " + context.length());
079    }
080
081    private static String suckFiles(String globURI) throws IOException {
082        var sb = new StringBuilder();
083        var rps = new ResourceProviders();
084        GlobResolver globResolver = new GlobResolvers();
085        try (var resources = globResolver.get(globURI)) {
086            forEach(resources, uri -> sb.append(rps.getResource(uri).charSource().read()));
087        }
088        return sb.toString();
089    }
090}