B4J Library Ollama4j library - Pnd_Ollama4j - Your local offline LLM like ChatGPT

What is Ollama?
Ollama is a free and open-source project that lets you run various open source LLMs locally.
For more info check this link.

Ollama for Windows and system requirements

Download Ollama server

Top LLMs for Coding All Developers Should Know About

Short video (3 minutes) about Ollama on You Tube

When you finish Ollama server installation, you can run example app to get model of your choice.
You can chat from application, download and delete models, for now.
When you choose model and tag, check DOWNLOAD SIZE, right bottom on image below, some models are over 200GB.
You can start with MODEL: mistral and TAG: 7b, download size is 4.1GB

Hardware requirements:
RAM: 8GB for running 3B models, 16GB for running 7B models, 32GB for running 13B models
Disk Space: 5GB for installing Ollama, additional space required for storing model data, depending on the models you use.
CPU: Any modern CPU with at least 4 cores is recommended, for running 13B models a CPU with at least 8 cores is recommended.
GPU(Optional): A GPU is not required for running Ollama, but it can improve performance, especially for running larger models. If you have a GPU, you can use it to accelerate training of custom models.




Chat example:




Versions:

v0.17
  • New methods: GenerateWithImageFiles and GenerateWithImageURLs
  • New example apps

v0.18
  • New class: Pnd_OllamaEmbedResponseModel
  • New method: Embed
  • New example app

v0.30
  • Lots of new classes to support chat feature
  • New method: Chat
  • Original library update to v1.0.91
  • New example apps


You can also check B4X AI Assistant based on this library (including B4J source code).

Wrapper is based on Ollama4j v1.0.91 from HERE.
This wrapper is in a very early stage of development, but you can try it.
Download library from: https://www.dropbox.com/scl/fi/e2wx...ey=fneim7i6rct2kzfsq8cvyp919&st=9ly5ihxr&dl=0
 

Attachments

  • Ollama4jExamples.zip
    117.6 KB · Views: 147
Last edited:

jmon

Well-Known Member
Licensed User
Longtime User
Last edited:

jmon

Well-Known Member
Licensed User
Longtime User
To compile as a standalone package you need to add this :
B4X:
#PackagerProperty: IncludedModules = java.sql

edit: hum.. I can't get it to work after compilation with the packager. I wonder if It need org.jsoup or com.sun or something else. I get this error:
java.lang.NoClassDefFoundError: com/sun/management/OperatingSystemMXBean
 
Last edited:

Pendrush

Well-Known Member
Licensed User
Longtime User
Can you try with:

B4X:
    #PackagerProperty: AdditionalModuleInfoString = exports org.slf4j;
    #PackagerProperty: AdditionalModuleInfoString = exports org.slf4j.spi;
    #PackagerProperty: AdditionalModuleInfoString = exports org.slf4j.event;
    #PackagerProperty: AdditionalModuleInfoString = exports org.slf4j.helpers;
    #PackagerProperty: AdditionalModuleInfoString = uses org.slf4j.spi.SLF4JServiceProvider;

    '#PackagerProperty: AdditionalModuleInfoString = requires transitive java.xml;
    #PackagerProperty: AdditionalModuleInfoString = exports com.fasterxml.jackson.annotation;
    #PackagerProperty: AdditionalModuleInfoString = opens com.fasterxml.jackson.annotation;
    '#PackagerProperty: AdditionalModuleInfoString = requires static org.jspecify;
    #PackagerProperty: AdditionalModuleInfoString = exports org.jsoup;
    #PackagerProperty: AdditionalModuleInfoString = exports org.jsoup.helper;
    #PackagerProperty: AdditionalModuleInfoString = exports org.jsoup.nodes;
    #PackagerProperty: AdditionalModuleInfoString = exports org.jsoup.parser;
    #PackagerProperty: AdditionalModuleInfoString = exports org.jsoup.safety;
    #PackagerProperty: AdditionalModuleInfoString = exports org.jsoup.select;
    #PackagerProperty: AdditionalModuleInfoString = requires java.logging;
    #PackagerProperty: AdditionalModuleInfoString = exports com.fasterxml.jackson.core;
    '#PackagerProperty: AdditionalModuleInfoString = requires transitive com.fasterxml.jackson.annotation;
    '#PackagerProperty: AdditionalModuleInfoString = requires transitive com.fasterxml.jackson.core;
    #PackagerProperty: AdditionalModuleInfoString = requires static java.sql;
    '#PackagerProperty: AdditionalModuleInfoString = requires static java.xml;
    #PackagerProperty: AdditionalModuleInfoString = requires static java.desktop;
    #PackagerProperty: AdditionalModuleInfoString = exports com.fasterxml.jackson.databind;
    #PackagerProperty: AdditionalModuleInfoString = exports com.fasterxml.jackson.databind.cfg;
    #PackagerProperty: AdditionalModuleInfoString = exports com.fasterxml.jackson.databind.annotation;
    #PackagerProperty: AdditionalModuleInfoString = exports com.fasterxml.jackson.databind.deser;
    #PackagerProperty: AdditionalModuleInfoString = exports com.fasterxml.jackson.databind.deser.impl;
    #PackagerProperty: AdditionalModuleInfoString = exports com.fasterxml.jackson.databind.deser.std;
    #PackagerProperty: AdditionalModuleInfoString = exports com.fasterxml.jackson.databind.exc;
    #PackagerProperty: AdditionalModuleInfoString = exports com.fasterxml.jackson.databind.ext;
    #PackagerProperty: AdditionalModuleInfoString = exports com.fasterxml.jackson.databind.introspect;
    #PackagerProperty: AdditionalModuleInfoString = exports com.fasterxml.jackson.databind.json;
    #PackagerProperty: AdditionalModuleInfoString = exports com.fasterxml.jackson.databind.jsonFormatVisitors;
    #PackagerProperty: AdditionalModuleInfoString = exports com.fasterxml.jackson.databind.jsonschema;
    #PackagerProperty: AdditionalModuleInfoString = exports com.fasterxml.jackson.databind.jsontype;
    #PackagerProperty: AdditionalModuleInfoString = exports com.fasterxml.jackson.databind.jsontype.impl;
    #PackagerProperty: AdditionalModuleInfoString = exports com.fasterxml.jackson.databind.module;
    #PackagerProperty: AdditionalModuleInfoString = exports com.fasterxml.jackson.databind.node;
    #PackagerProperty: AdditionalModuleInfoString = exports com.fasterxml.jackson.databind.ser;
    #PackagerProperty: AdditionalModuleInfoString = exports com.fasterxml.jackson.databind.ser.impl;
    #PackagerProperty: AdditionalModuleInfoString = exports com.fasterxml.jackson.databind.ser.std;
    #PackagerProperty: AdditionalModuleInfoString = exports com.fasterxml.jackson.databind.type;
    #PackagerProperty: AdditionalModuleInfoString = exports com.fasterxml.jackson.databind.util;
    '#PackagerProperty: AdditionalModuleInfoString = uses com.fasterxml.jackson.databind.Module;
    #PackagerProperty: AdditionalModuleInfoString = provides com.fasterxml.jackson.core.ObjectCodec with com.fasterxml.jackson.databind.ObjectMapper;

For some reason I also need to add on top:
B4X:
    #PackagerProperty: IncludedModules = javafx.swing
    #PackagerProperty: IncludedModules = java.net.http
    #PackagerProperty: IncludedModules = javafx.controls

Example app is updated.
 
Last edited:

Pendrush

Well-Known Member
Licensed User
Longtime User
Test model with question to optimize B4X code.

Model: qwen2.5-coder:14b


Question:
Your task is to improve the code's efficiency, readability, and adherence to best practices without changing its core functionality.
Analyze the code and suggest optimizations that could improve its performance, readability, or maintainability. Focus on:
Reducing time complexity
Improving space efficiency
Enhancing code readability
Applying relevant design patterns or coding best practices
Provide your optimized version of the code, along with brief comments explaining the key changes and their benefits.
Keep your response concise and focused on the most impactful optimizations.
Here's the code to optimize writen with B4X language:
B4X:
Dim Result As Pnd_OllamaAsyncResult = Main.Ollama.GenerateAsync(cBox.Value, txtInput.Text, False)
    Do While True
        Dim Token As String = Result.StreamPool
        txtOutput.Text = txtOutput.Text & Token.Replace("\n", CRLF)
        txtOutput.SetSelection(txtOutput.Text.Length, txtOutput.Text.Length)
        If Result.IsAlive = False Then
            txtOutput.Text = txtOutput.Text & CRLF & CRLF
            txtOutput.SetSelection(txtOutput.Text.Length, txtOutput.Text.Length)
            Exit
        End If
        Sleep(100)
    Loop


Answer:
To optimize the provided code, we can focus on reducing unnecessary operations, improving readability, and ensuring better performance. Here are the key changes:

1. **Avoid Concatenating Strings in a Loop**: Instead of appending strings in each iteration, use a `StringBuilder` to reduce memory allocation overhead.
2. **Use Constants for Magic Numbers**: Replace magic numbers like `100` with named constants for better readability and maintainability.
3. **Optimize the Exit Condition**: Ensure that the loop exits as soon as possible by checking the exit condition more frequently.
4. **Improve Readability with Clear Naming**: Use clear and descriptive variable names to enhance code readability.

Here is the optimized version of the code:

B4X:
' Constants for better readability and maintainability
Dim POLL_INTERVAL As Int = 100 ' milliseconds

' Use StringBuilder for efficient string concatenation
Dim outputBuilder As StringBuilder
outputBuilder.Initialize

' Start the asynchronous generation process
Dim result As Pnd_OllamaAsyncResult = Main.Ollama.GenerateAsync(cBox.Value, txtInput.Text, False)

Do While True
    ' Fetch the next token from the stream pool
    Dim token As String = Result.StreamPool

    ' Append the token to the output builder, replacing newlines with CRLF
    outputBuilder.Append(token.Replace("\n", CRLF))

    ' Update the text box with the current content of the StringBuilder
    txtOutput.Text = outputBuilder.ToString()
    txtOutput.SetSelection(txtOutput.Text.Length, txtOutput.Text.Length)

    ' Check if the asynchronous process is complete
    If Result.IsAlive = False Then

        ' Append two newlines and update the selection position
        outputBuilder.Append(CRLF & CRLF)
        txtOutput.Text = outputBuilder.ToString()
        txtOutput.SetSelection(txtOutput.Text.Length, txtOutput.Text.Length)
     
        ' Exit the loop as the process is complete
        Exit
    End If
 
    ' Sleep for a short period before checking again
    Sleep(POLL_INTERVAL)
Loop


### Key Changes and Benefits:

1. **StringBuilder**: By using `StringBuilder`, we avoid creating multiple intermediate string objects, which reduces memory usage and improves performance.
2. **Constants**: The use of named constants (`POLL_INTERVAL`) makes the code more readable and easier to maintain.
3. **Efficient Updates**: Updating the text box only once per loop iteration (after appending all tokens) minimizes unnecessary UI updates, improving responsiveness.
4. **Clear Naming**: Descriptive variable names like `outputBuilder` make the code easier to understand.

These changes should enhance the performance, readability, and maintainability of the code without altering its core functionality.
-- END OF ANSWER --


 
Last edited:

jmon

Well-Known Member
Licensed User
Longtime User
It compiles, but after installation it doesn't run and gives this error, I wonder if there is a conflit with AWTRobot or something:

 

Pendrush

Well-Known Member
Licensed User
Longtime User
Any possibility to implement the other functions:
"OllamaEmbedResponseModel" ?

I could help on the source if you need help
I will implement OllamaEmbedResponseModel but I need to find some free time to do it.
 

jmon

Well-Known Member
Licensed User
Longtime User
It compiles, but after installation it doesn't run and gives this error, I wonder if there is a conflit with AWTRobot or something:
Hi,

This is the list of imports that works for me. Somehow the one you listed created problems with AWT Robot and HikariCP.

B4X:
    #PackagerProperty: IncludedModules = javafx.swing
    #PackagerProperty: IncludedModules = java.net.http
    #PackagerProperty: IncludedModules = javafx.controls
'    #PackagerProperty: IncludedModules = javax.management
'    #PackagerProperty: IncludedModules = java.lang.management
'    #PackagerProperty: IncludedModules = java.sql
    #PackagerProperty: AdditionalModuleInfoString = exports org.slf4j;
    #PackagerProperty: AdditionalModuleInfoString = exports org.slf4j.spi;
    #PackagerProperty: AdditionalModuleInfoString = exports org.slf4j.event;
    #PackagerProperty: AdditionalModuleInfoString = exports org.slf4j.helpers;
    #PackagerProperty: AdditionalModuleInfoString = uses org.slf4j.spi.SLF4JServiceProvider;
    '#PackagerProperty: AdditionalModuleInfoString = requires transitive java.xml;
    #PackagerProperty: AdditionalModuleInfoString = exports com.fasterxml.jackson.annotation;
    #PackagerProperty: AdditionalModuleInfoString = opens com.fasterxml.jackson.annotation;
    '#PackagerProperty: AdditionalModuleInfoString = requires static org.jspecify;
    #PackagerProperty: AdditionalModuleInfoString = exports org.jsoup;
    #PackagerProperty: AdditionalModuleInfoString = exports org.jsoup.helper;
    #PackagerProperty: AdditionalModuleInfoString = exports org.jsoup.nodes;
    #PackagerProperty: AdditionalModuleInfoString = exports org.jsoup.parser;
    #PackagerProperty: AdditionalModuleInfoString = exports org.jsoup.safety;
    #PackagerProperty: AdditionalModuleInfoString = exports org.jsoup.select;
    #PackagerProperty: AdditionalModuleInfoString = requires java.logging;
    #PackagerProperty: AdditionalModuleInfoString = exports com.fasterxml.jackson.core;
    '#PackagerProperty: AdditionalModuleInfoString = requires transitive com.fasterxml.jackson.annotation;
    '#PackagerProperty: AdditionalModuleInfoString = requires transitive com.fasterxml.jackson.core;
    #PackagerProperty: AdditionalModuleInfoString = requires java.naming; 'Added
    #PackagerProperty: AdditionalModuleInfoString = requires jdk.management; 'Added
    #PackagerProperty: AdditionalModuleInfoString = requires java.sql; 'Changed
    #PackagerProperty: AdditionalModuleInfoString = requires javafx.fxml; requires javafx.graphics; 'Added
'    #PackagerProperty: AdditionalModuleInfoString = requires static java.sql;
    '#PackagerProperty: AdditionalModuleInfoString = requires static java.xml;
    #PackagerProperty: AdditionalModuleInfoString = requires static java.desktop;
    #PackagerProperty: AdditionalModuleInfoString = exports com.fasterxml.jackson.databind;
    #PackagerProperty: AdditionalModuleInfoString = exports com.fasterxml.jackson.databind.cfg;
    #PackagerProperty: AdditionalModuleInfoString = exports com.fasterxml.jackson.databind.annotation;
    #PackagerProperty: AdditionalModuleInfoString = exports com.fasterxml.jackson.databind.deser;
    #PackagerProperty: AdditionalModuleInfoString = exports com.fasterxml.jackson.databind.deser.impl;
    #PackagerProperty: AdditionalModuleInfoString = exports com.fasterxml.jackson.databind.deser.std;
    #PackagerProperty: AdditionalModuleInfoString = exports com.fasterxml.jackson.databind.exc;
    #PackagerProperty: AdditionalModuleInfoString = exports com.fasterxml.jackson.databind.ext;
    #PackagerProperty: AdditionalModuleInfoString = exports com.fasterxml.jackson.databind.introspect;
    #PackagerProperty: AdditionalModuleInfoString = exports com.fasterxml.jackson.databind.json;
    #PackagerProperty: AdditionalModuleInfoString = exports com.fasterxml.jackson.databind.jsonFormatVisitors;
    #PackagerProperty: AdditionalModuleInfoString = exports com.fasterxml.jackson.databind.jsonschema;
    #PackagerProperty: AdditionalModuleInfoString = exports com.fasterxml.jackson.databind.jsontype;
    #PackagerProperty: AdditionalModuleInfoString = exports com.fasterxml.jackson.databind.jsontype.impl;
    #PackagerProperty: AdditionalModuleInfoString = exports com.fasterxml.jackson.databind.module;
    #PackagerProperty: AdditionalModuleInfoString = exports com.fasterxml.jackson.databind.node;
    #PackagerProperty: AdditionalModuleInfoString = exports com.fasterxml.jackson.databind.ser;
    #PackagerProperty: AdditionalModuleInfoString = exports com.fasterxml.jackson.databind.ser.impl;
    #PackagerProperty: AdditionalModuleInfoString = exports com.fasterxml.jackson.databind.ser.std;
    #PackagerProperty: AdditionalModuleInfoString = exports com.fasterxml.jackson.databind.type;
    #PackagerProperty: AdditionalModuleInfoString = exports com.fasterxml.jackson.databind.util;
    '#PackagerProperty: AdditionalModuleInfoString = uses com.fasterxml.jackson.databind.Module;
    #PackagerProperty: AdditionalModuleInfoString = provides com.fasterxml.jackson.core.ObjectCodec with com.fasterxml.jackson.databind.ObjectMapper;
I'm not good with this packager imports, but the changes are:

1: Removed the "static" from requires static java.sql
2: Added requires java.naming;
3: Added requires jdk.management;
4: Added requires javafx.fxml; requires javafx.graphics;


What do you think?
 
Last edited:
Cookies are required to use this site. You must accept them to continue using the site. Learn more…