Skip to content

Commit bdb84b8

Browse files
authored
Merge pull request #53 from matlab-deep-learning/remote-ollama
Add support for remote ollama
2 parents d42e09d + 761a843 commit bdb84b8

File tree

7 files changed

+44
-11
lines changed

7 files changed

+44
-11
lines changed

+llms/+internal/callOllamaChatAPI.m

+5-1
Original file line numberDiff line numberDiff line change
@@ -37,9 +37,13 @@
3737
nvp.Seed
3838
nvp.TimeOut
3939
nvp.StreamFun
40+
nvp.Endpoint
4041
end
4142

42-
URL = "http://localhost:11434/api/chat";
43+
URL = nvp.Endpoint + "/api/chat";
44+
if ~startsWith(URL,"http")
45+
URL = "http://" + URL;
46+
end
4347

4448
% The JSON for StopSequences must have an array, and cannot say "stop": "foo".
4549
% The easiest way to ensure that is to never pass in a scalar …

.github/workflows/ci.yml

+6-1
Original file line numberDiff line numberDiff line change
@@ -14,19 +14,23 @@ jobs:
1414
run: |
1515
# Run the background, there is no way to daemonise at the moment
1616
ollama serve &
17+
# Run a second server to test different endpoint
18+
OLLAMA_HOST=127.0.0.1:11435 OLLAMA_MODELS=/tmp/ollama/models ollama serve &
1719
1820
# A short pause is required before the HTTP port is opened
1921
sleep 5
2022
2123
# This endpoint blocks until ready
2224
time curl -i http://localhost:11434
25+
time curl -i http://localhost:11435
2326
2427
# For debugging, record Ollama version
2528
ollama --version
2629
27-
- name: Pull mistral model
30+
- name: Pull models
2831
run: |
2932
ollama pull mistral
33+
OLLAMA_HOST=127.0.0.1:11435 ollama pull qwen2:0.5b
3034
- name: Set up MATLAB
3135
uses: matlab-actions/setup-matlab@v2
3236
with:
@@ -39,6 +43,7 @@ jobs:
3943
AZURE_OPENAI_DEPLOYMENT: ${{ secrets.AZURE_DEPLOYMENT }}
4044
AZURE_OPENAI_ENDPOINT: ${{ secrets.AZURE_ENDPOINT }}
4145
AZURE_OPENAI_API_KEY: ${{ secrets.AZURE_KEY }}
46+
SECOND_OLLAMA_ENDPOINT: 127.0.0.1:11435
4247
uses: matlab-actions/run-tests@v2
4348
with:
4449
test-results-junit: test-results/results.xml

.gitignore

+2
Original file line numberDiff line numberDiff line change
@@ -6,3 +6,5 @@ papers_to_read.csv
66
data/*
77
examples/data/*
88
._*
9+
.nfs*
10+
.DS_Store

README.md

+2-2
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
[![Open in MATLAB Online](https://www.mathworks.com/images/responsive/global/open-in-matlab-online.svg)](https://matlab.mathworks.com/open/github/v1?repo=matlab-deep-learning/llms-with-matlab) [![View Large Language Models (LLMs) with MATLAB on File Exchange](https://www.mathworks.com/matlabcentral/images/matlab-file-exchange.svg)](https://www.mathworks.com/matlabcentral/fileexchange/163796-large-language-models-llms-with-matlab)
44

5-
This repository contains code to connect MATLAB to the [OpenAI™ Chat Completions API](https://platform.openai.com/docs/guides/text-generation/chat-completions-api) (which powers ChatGPT™), OpenAI Images API (which powers DALL·E™), [Azure® OpenAI Service](https://learn.microsoft.com/en-us/azure/ai-services/openai/), and local [Ollama®](https://ollama.com/) models. This allows you to leverage the natural language processing capabilities of large language models directly within your MATLAB environment.
5+
This repository contains code to connect MATLAB to the [OpenAI™ Chat Completions API](https://platform.openai.com/docs/guides/text-generation/chat-completions-api) (which powers ChatGPT™), OpenAI Images API (which powers DALL·E™), [Azure® OpenAI Service](https://learn.microsoft.com/en-us/azure/ai-services/openai/), and both local and nonlocal [Ollama®](https://ollama.com/) models. This allows you to leverage the natural language processing capabilities of large language models directly within your MATLAB environment.
66

77
## Requirements
88

@@ -15,7 +15,7 @@ This repository contains code to connect MATLAB to the [OpenAI™ Chat Completio
1515

1616
- For OpenAI connections: An active OpenAI API subscription and API key.
1717
- For Azure OpenAI Services: An active Azure subscription with OpenAI access, deployment, and API key.
18-
- For Ollama: A local Ollama installation. Currently, only connections on `localhost` are supported, i.e., Ollama and MATLAB must run on the same machine.
18+
- For Ollama: An Ollama installation.
1919

2020
## Setup
2121

doc/Ollama.md

+9-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# Ollama
22

3-
This repository contains code to connect MATLAB to a local [Ollama®](https://ollama.com) server, running large language models (LLMs).
3+
This repository contains code to connect MATLAB to an [Ollama®](https://ollama.com) server, running large language models (LLMs).
44

55
To use local models with Ollama, you will need to install and start an Ollama server, and “pull” models into it. Please follow the Ollama documentation for details. You should be familiar with the limitations and risks associated with using this technology, and you agree that you shall be solely responsible for full compliance with any terms that may apply to your use of any specific model.
66

@@ -13,7 +13,7 @@ Some of the [LLMs currently supported out of the box on Ollama](https://ollama.c
1313
- gemma, codegemma
1414
- command-r
1515

16-
## Establishing a connection to local LLMs using Ollama
16+
## Establishing a connection to LLMs using Ollama
1717

1818
To create the chat assistant, call `ollamaChat` and specify the LLM you want to use:
1919
```matlab
@@ -95,3 +95,10 @@ chat = ollamaChat("mistral", StreamFun=sf);
9595
txt = generate(chat,"What is Model-Based Design and how is it related to Digital Twin?");
9696
% Should stream the response token by token
9797
```
98+
99+
## Establishing a connection to remote LLMs using Ollama
100+
101+
To connect to a remote Ollama server, use the `Endpoint` name-value pair. Include the server name and port number. Ollama starts on 11434 by default.
102+
```matlab
103+
chat = ollamaChat("mistral",Endpoint="ollamaServer:11434");
104+
```

ollamaChat.m

+7-3
Original file line numberDiff line numberDiff line change
@@ -64,8 +64,9 @@
6464
% Copyright 2024 The MathWorks, Inc.
6565

6666
properties
67-
Model (1,1) string
68-
TopK (1,1) {mustBeReal,mustBePositive} = Inf
67+
Model (1,1) string
68+
Endpoint (1,1) string
69+
TopK (1,1) {mustBeReal,mustBePositive} = Inf
6970
TailFreeSamplingZ (1,1) {mustBeReal} = 1
7071
end
7172

@@ -82,6 +83,7 @@
8283
nvp.TimeOut (1,1) {mustBeReal,mustBePositive} = 120
8384
nvp.TailFreeSamplingZ (1,1) {mustBeReal} = 1
8485
nvp.StreamFun (1,1) {mustBeA(nvp.StreamFun,'function_handle')}
86+
nvp.Endpoint (1,1) string = "127.0.0.1:11434"
8587
end
8688

8789
if isfield(nvp,"StreamFun")
@@ -105,6 +107,7 @@
105107
this.TailFreeSamplingZ = nvp.TailFreeSamplingZ;
106108
this.StopSequences = nvp.StopSequences;
107109
this.TimeOut = nvp.TimeOut;
110+
this.Endpoint = nvp.Endpoint;
108111
end
109112

110113
function [text, message, response] = generate(this, messages, nvp)
@@ -147,7 +150,8 @@
147150
TailFreeSamplingZ=this.TailFreeSamplingZ,...
148151
StopSequences=this.StopSequences, MaxNumTokens=nvp.MaxNumTokens, ...
149152
ResponseFormat=this.ResponseFormat,Seed=nvp.Seed, ...
150-
TimeOut=this.TimeOut, StreamFun=this.StreamFun);
153+
TimeOut=this.TimeOut, StreamFun=this.StreamFun, ...
154+
Endpoint=this.Endpoint);
151155

152156
if isfield(response.Body.Data,"error")
153157
err = response.Body.Data.error;

tests/tollamaChat.m

+13-2
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,6 @@ function seedFixesResult(testCase)
9898
testCase.verifyEqual(response1,response2);
9999
end
100100

101-
102101
function streamFunc(testCase)
103102
function seen = sf(str)
104103
persistent data;
@@ -118,6 +117,19 @@ function streamFunc(testCase)
118117
testCase.verifyGreaterThan(numel(sf("")), 1);
119118
end
120119

120+
function reactToEndpoint(testCase)
121+
testCase.assumeTrue(isenv("SECOND_OLLAMA_ENDPOINT"),...
122+
"Test point assumes a second Ollama server is running " + ...
123+
"and $SECOND_OLLAMA_ENDPOINT points to it.");
124+
chat = ollamaChat("qwen2:0.5b",Endpoint=getenv("SECOND_OLLAMA_ENDPOINT"));
125+
testCase.verifyWarningFree(@() generate(chat,"dummy"));
126+
% also make sure "http://" can be included
127+
chat = ollamaChat("qwen2:0.5b",Endpoint="http://" + getenv("SECOND_OLLAMA_ENDPOINT"));
128+
response = generate(chat,"some input");
129+
testCase.verifyClass(response,'string');
130+
testCase.verifyGreaterThan(strlength(response),0);
131+
end
132+
121133
function doReturnErrors(testCase)
122134
testCase.assumeFalse( ...
123135
any(startsWith(ollamaChat.models,"abcdefghijklmnop")), ...
@@ -126,7 +138,6 @@ function doReturnErrors(testCase)
126138
testCase.verifyError(@() generate(chat,"hi!"), "llms:apiReturnedError");
127139
end
128140

129-
130141
function invalidInputsConstructor(testCase, InvalidConstructorInput)
131142
testCase.verifyError(@() ollamaChat("mistral", InvalidConstructorInput.Input{:}), InvalidConstructorInput.Error);
132143
end

0 commit comments

Comments
 (0)