Compare commits

...

4 Commits

Author SHA1 Message Date
amithkoujalgi
5b3713c69e added getLibraryModelDetails API and pullModel API with LibraryModelTag 2024-11-08 11:23:47 +05:30
Amith Koujalgi
e9486cbb8e Merge pull request #76 from ollama4j/model-listing
updated `listModelsFromLibrary` API
2024-11-08 10:05:19 +05:30
amithkoujalgi
057f0babeb updated listModelsFromLibrary API
updated `listModelsFromLibrary` API
2024-11-08 10:02:27 +05:30
Amith Koujalgi
da146640ca Update README.md 2024-11-08 00:08:13 +05:30
7 changed files with 202 additions and 1337 deletions

View File

@@ -154,7 +154,7 @@ In your Maven project, add this dependency:
<dependency>
<groupId>io.github.ollama4j</groupId>
<artifactId>ollama4j</artifactId>
<version>1.0.79</version>
<version>1.0.87</version>
</dependency>
```

File diff suppressed because it is too large Load Diff

View File

@@ -4,7 +4,7 @@ sidebar_position: 1
# List Models
This API lets you list available models on the Ollama server.
This API lets you list downloaded/available models on the Ollama server.
```java title="ListModels.java"
import io.github.ollama4j.OllamaAPI;

View File

@@ -194,16 +194,30 @@ public class OllamaAPI {
for (Element e : modelSections) {
LibraryModel model = new LibraryModel();
Elements names = e.select("div > h2 > span");
Elements desc = e.select("div > p");
Elements pullCounts = e.select("div:nth-of-type(2) > p > span:first-of-type > span:first-of-type");
Elements popularTags = e.select("div > div > span");
Elements tagCount = e.select("div:nth-of-type(2) > p > span:nth-of-type(2) > span:first-of-type");
Elements updatedAt = e.select("div:nth-of-type(2) > p > span:nth-of-type(3) > span:nth-of-type(2)");
Elements totalTags = e.select("div:nth-of-type(2) > p > span:nth-of-type(2) > span:first-of-type");
Elements lastUpdatedTime = e.select("div:nth-of-type(2) > p > span:nth-of-type(3) > span:nth-of-type(2)");
if (names.first() == null || names.isEmpty()) {
// if name cannot be extracted, skip.
continue;
}
Optional.ofNullable(names.first())
.map(Element::text)
.ifPresent(model::setName);
model.setDescription(Optional.ofNullable(desc.first()).map(Element::text).orElse(""));
model.setPopularTags(Optional.of(popularTags)
.map(tags -> tags.stream().map(Element::text).collect(Collectors.toList()))
.orElse(new ArrayList<>()));
model.setPullCount(Optional.ofNullable(pullCounts.first()).map(Element::text).orElse(""));
model.setTotalTags(Optional.ofNullable(totalTags.first())
.map(Element::text)
.map(Integer::parseInt)
.orElse(0));
model.setLastUpdated(Optional.ofNullable(lastUpdatedTime.first()).map(Element::text).orElse(""));
model.setName(names.first().text());
model.setPullCount(pullCounts.first().text());
model.setPopularTags(popularTags.stream().map(Element::text).collect(Collectors.toList()));
model.setNumTags(Integer.parseInt(tagCount.first().text()));
model.setUpdatedAt(updatedAt.first().text());
models.add(model);
}
return models;
@@ -212,6 +226,67 @@ public class OllamaAPI {
}
}
/**
* Fetches the tags associated with a specific model from Ollama library.
* This method fetches the available model tags directly from Ollama library model page, including model tag name, size and time when model was last updated
* into a list of {@link LibraryModelTag} objects.
*
* @param libraryModel the {@link LibraryModel} object which contains the name of the library model
* for which the tags need to be fetched.
* @return a list of {@link LibraryModelTag} objects containing the extracted tags and their associated metadata.
* @throws OllamaBaseException if the HTTP response status code indicates an error (i.e., not 200 OK),
* or if there is any other issue during the request or response processing.
* @throws IOException if an input/output exception occurs during the HTTP request or response handling.
* @throws InterruptedException if the thread is interrupted while waiting for the HTTP response.
* @throws URISyntaxException if the URI format is incorrect or invalid.
*/
public LibraryModelDetail getLibraryModelDetails(LibraryModel libraryModel) throws OllamaBaseException, IOException, InterruptedException, URISyntaxException {
String url = String.format("https://ollama.com/library/%s/tags", libraryModel.getName());
HttpClient httpClient = HttpClient.newHttpClient();
HttpRequest httpRequest = getRequestBuilderDefault(new URI(url)).header("Accept", "application/json").header("Content-type", "application/json").GET().build();
HttpResponse<String> response = httpClient.send(httpRequest, HttpResponse.BodyHandlers.ofString());
int statusCode = response.statusCode();
String responseString = response.body();
List<LibraryModelTag> libraryModelTags = new ArrayList<>();
if (statusCode == 200) {
Document doc = Jsoup.parse(responseString);
Elements tagSections = doc.select("html > body > main > div > section > div > div > div:nth-child(n+2) > div");
for (Element e : tagSections) {
Elements tags = e.select("div > a > div");
Elements tagsMetas = e.select("div > span");
LibraryModelTag libraryModelTag = new LibraryModelTag();
if (tags.first() == null || tags.isEmpty()) {
// if tag cannot be extracted, skip.
continue;
}
libraryModelTag.setName(libraryModel.getName());
Optional.ofNullable(tags.first())
.map(Element::text)
.ifPresent(libraryModelTag::setTag);
libraryModelTag.setSize(Optional.ofNullable(tagsMetas.first())
.map(element -> element.text().split(""))
.filter(parts -> parts.length > 1)
.map(parts -> parts[1].trim())
.orElse(""));
libraryModelTag.setLastUpdated(Optional.ofNullable(tagsMetas.first())
.map(element -> element.text().split(""))
.filter(parts -> parts.length > 1)
.map(parts -> parts[2].trim())
.orElse(""));
libraryModelTags.add(libraryModelTag);
}
LibraryModelDetail libraryModelDetail = new LibraryModelDetail();
libraryModelDetail.setModel(libraryModel);
libraryModelDetail.setTags(libraryModelTags);
return libraryModelDetail;
} else {
throw new OllamaBaseException(statusCode + " - " + responseString);
}
}
/**
* Pull a model on the Ollama server from the list of <a
* href="https://ollama.ai/library">available models</a>.
@@ -245,6 +320,23 @@ public class OllamaAPI {
}
}
/**
* Pulls a model using the specified Ollama library model tag.
* The model is identified by a name and a tag, which are combined into a single identifier
* in the format "name:tag" to pull the corresponding model.
*
* @param libraryModelTag the {@link LibraryModelTag} object containing the name and tag
* of the model to be pulled.
* @throws OllamaBaseException if the response indicates an error status
* @throws IOException if an I/O error occurs during the HTTP request
* @throws InterruptedException if the operation is interrupted
* @throws URISyntaxException if the URI for the request is malformed
*/
public void pullModel(LibraryModelTag libraryModelTag) throws OllamaBaseException, IOException, URISyntaxException, InterruptedException {
String tagToPull = String.format("%s:%s", libraryModelTag.getName(), libraryModelTag.getTag());
pullModel(tagToPull);
}
/**
* Gets model details from the Ollama server.
*

View File

@@ -8,8 +8,9 @@ import lombok.Data;
public class LibraryModel {
private String name;
private String description;
private String pullCount;
private int numTags;
private int totalTags;
private List<String> popularTags = new ArrayList<>();
private String updatedAt;
private String lastUpdated;
}

View File

@@ -0,0 +1,12 @@
package io.github.ollama4j.models.response;
import lombok.Data;
import java.util.List;
@Data
public class LibraryModelDetail {
private LibraryModel model;
private List<LibraryModelTag> tags;
}

View File

@@ -0,0 +1,13 @@
package io.github.ollama4j.models.response;
import lombok.Data;
import java.util.List;
@Data
public class LibraryModelTag {
private String name;
private String tag;
private String size;
private String lastUpdated;
}