Skip to content

Commit

Permalink
Use a bitmask for capabilities in OllamaModelsDB and upload SQL schema
Browse files Browse the repository at this point in the history
  • Loading branch information
WilliamKarolDiCioccio committed Sep 28, 2024
1 parent 50d79a2 commit 2734d82
Show file tree
Hide file tree
Showing 5 changed files with 83 additions and 33 deletions.
44 changes: 33 additions & 11 deletions app/lib/backend/private/storage/ollama_models.dart
Original file line number Diff line number Diff line change
Expand Up @@ -36,10 +36,7 @@ class OllamaModelsDB {
name TEXT UNIQUE,
description TEXT,
url TEXT,
vision BOOLEAN,
tools BOOLEAN,
embedding BOOLEAN,
code BOOLEAN
capabilities INTEGER
)
''');

Expand All @@ -53,9 +50,13 @@ class OllamaModelsDB {
)
''');

_db!.execute('CREATE INDEX IF NOT EXISTS idx_model_name ON models (name)');
_db!.execute(
'CREATE INDEX IF NOT EXISTS idx_model_capabilities ON models (vision, tools, embedding, code)');
'CREATE INDEX IF NOT EXISTS idx_model_name ON models (name)',
);

_db!.execute(
'CREATE INDEX IF NOT EXISTS idx_model_capabilities ON models (capabilities)',
);

debugPrint("Database initialized at $dbPath");
}
Expand Down Expand Up @@ -91,23 +92,44 @@ class OllamaModelsDB {
return result.isNotEmpty;
}

// Check if a model supports a specific feature (vision, tools, embedding, or code)
bool doesModelSupport(String name, String feature) {
// Get the capabilities of a model by its name
List<String> getModelCapabilities(String name) {
if (_db == null) {
throw Exception("Database not initialized");
}

final result = _db!.select(
'SELECT $feature FROM models WHERE name = ?',
'SELECT capabilities FROM models WHERE name = ?',
[name],
);

if (result.isEmpty) {
return false;
return [];
}

final model = result.first;
return model[feature] == 1;
final int capabilities = model['capabilities'];
final List<String> availableCapabilities = [];

const int visionMask = 1 << 0;
const int toolsMask = 1 << 1;
const int embeddingMask = 1 << 2;
const int codeMask = 1 << 3;

if ((capabilities & visionMask) != 0) {
availableCapabilities.add('vision');
}
if ((capabilities & toolsMask) != 0) {
availableCapabilities.add('tools');
}
if ((capabilities & embeddingMask) != 0) {
availableCapabilities.add('embedding');
}
if ((capabilities & codeMask) != 0) {
availableCapabilities.add('code');
}

return availableCapabilities;
}

// Get the description of a model by its name
Expand Down
11 changes: 7 additions & 4 deletions app/lib/frontend/pages/dashboard/models.dart
Original file line number Diff line number Diff line change
Expand Up @@ -365,8 +365,11 @@ class _ModelListTileState extends State<ModelListTile> {
}

final tags = <Widget>[];
final capabilities = db.getModelCapabilities(cleanModelName);

if (db.doesModelSupport(cleanModelName, 'vision')) {
if (capabilities.isEmpty) return const SizedBox.shrink();

if (capabilities.contains('vision')) {
tags.add(
Chip(
avatar: const Icon(
Expand All @@ -391,7 +394,7 @@ class _ModelListTileState extends State<ModelListTile> {
);
}

if (db.doesModelSupport(cleanModelName, 'tools')) {
if (capabilities.contains('tools')) {
tags.add(
Chip(
avatar: const Icon(
Expand All @@ -416,7 +419,7 @@ class _ModelListTileState extends State<ModelListTile> {
);
}

if (db.doesModelSupport(cleanModelName, 'embedding')) {
if (capabilities.contains('embedding')) {
tags.add(
Chip(
avatar: const Icon(
Expand All @@ -441,7 +444,7 @@ class _ModelListTileState extends State<ModelListTile> {
);
}

if (db.doesModelSupport(cleanModelName, 'code')) {
if (capabilities.contains('code')) {
tags.add(
Chip(
avatar: const Icon(
Expand Down
Binary file added database/ollama_models.sql
Binary file not shown.
16 changes: 9 additions & 7 deletions scripts/create_ollama_models_db.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,17 +6,17 @@ def create_database_schema():
conn = sqlite3.connect('ollama_models.db')
c = conn.cursor()

# Create table for models with a 'url' column
# Create table for models
# Even doe using an integer bitmask to store capabilities is a waste of local storage
# as SQLite INTEGER takes 64-bit while four bools take 8-bits each for a total of 32-bits,
# it saves space in the cloud storage and makes querying faster that uses PostgreSQL
c.execute('''
CREATE TABLE IF NOT EXISTS models (
id INTEGER PRIMARY KEY AUTOINCREMENT,
name TEXT UNIQUE,
description TEXT,
url TEXT,
vision BOOLEAN,
tools BOOLEAN,
embedding BOOLEAN,
code BOOLEAN
capabilities INTEGER
)
''')

Expand All @@ -31,9 +31,11 @@ def create_database_schema():
)
''')

# Create indexes on model attributes for fast querying
# Create an index on the model name for fast querying
c.execute('CREATE INDEX IF NOT EXISTS idx_model_name ON models (name)')
c.execute('CREATE INDEX IF NOT EXISTS idx_model_capabilities ON models (vision, tools, embedding, code)')

# Create an index on the model capabilities for fast querying
c.execute('CREATE INDEX IF NOT EXISTS idx_model_capabilities ON models (capabilities)')

# Commit the transaction and close the connection
conn.commit()
Expand Down
45 changes: 34 additions & 11 deletions scripts/scrape_ollama_library.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,19 @@
from datetime import datetime


def calculate_capabilities(vision=False, tools=False, embedding=False, code=False):
capabilities = 0
if vision:
capabilities |= 1 # 1st bit for vision
if tools:
capabilities |= 2 # 2nd bit for tools
if embedding:
capabilities |= 4 # 3rd bit for embedding
if code:
capabilities |= 8 # 4th bit for code
return capabilities


def get_soup(url):
response = requests.get(url)
if response.status_code == 200: # Check if the request was successful
Expand Down Expand Up @@ -92,17 +105,17 @@ def save_data_to_sqlite(models_info):
conn = sqlite3.connect('ollama_models.db')
c = conn.cursor()

# Create table for models with a 'url' column
# Create table for models
# Even doe using an integer bitmask to store capabilities is a waste of local storage
# as SQLite INTEGER takes 64-bit while four bools take 8-bits each for a total of 32-bits,
# it saves space in the cloud storage and makes querying faster that uses PostgreSQL
c.execute('''
CREATE TABLE IF NOT EXISTS models (
id INTEGER PRIMARY KEY AUTOINCREMENT,
name TEXT UNIQUE,
description TEXT,
url TEXT, -- Include 'url' column here
vision BOOLEAN,
tools BOOLEAN,
embedding BOOLEAN,
code BOOLEAN
url TEXT,
capabilities INTEGER
)
''')

Expand All @@ -117,17 +130,27 @@ def save_data_to_sqlite(models_info):
)
''')

# Create indexes on model attributes for fast querying
# Create an index on the model name for fast querying
c.execute('CREATE INDEX IF NOT EXISTS idx_model_name ON models (name)')
c.execute('CREATE INDEX IF NOT EXISTS idx_model_capabilities ON models (vision, tools, embedding, code)')

# Create an index on the model capabilities for fast querying
c.execute('CREATE INDEX IF NOT EXISTS idx_model_capabilities ON models (capabilities)')

# Insert data into the tables
for model_name, details in models_info.items():
# Calculate the capabilities bitmask
capabilities_value = calculate_capabilities(
vision=details['vision'],
tools=details['tools'],
embedding=details['embedding'],
code=details['code']
)

# Insert the model details into the models table
c.execute('''
INSERT OR IGNORE INTO models (name, description, url, vision, tools, embedding, code)
VALUES (?, ?, ?, ?, ?, ?, ?)
''', (model_name, details['description'], details['url'], details['vision'], details['tools'], details['embedding'], details['code']))
INSERT OR IGNORE INTO models (name, description, url, capabilities)
VALUES (?, ?, ?, ?)
''', (model_name, details['description'], details['url'], capabilities_value))

# Get the last inserted model ID (or fetch the existing one)
c.execute('SELECT id FROM models WHERE name = ?', (model_name,))
Expand Down

0 comments on commit 2734d82

Please sign in to comment.