Skip to content

Commit 7abec62

Browse files
committed
OpenConceptLab/ocl_issues#2307 | Multi Algo configuration
1 parent 8891183 commit 7abec62

File tree

5 files changed

+145
-19
lines changed

5 files changed

+145
-19
lines changed
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
# Generated by Django 4.2.16 on 2026-02-06 06:30
2+
3+
import django.contrib.postgres.fields
4+
from django.db import migrations, models
5+
6+
7+
class Migration(migrations.Migration):
8+
9+
dependencies = [
10+
('map_projects', '0023_remove_mapproject_reranker'),
11+
]
12+
13+
operations = [
14+
migrations.AddField(
15+
model_name='mapproject',
16+
name='algorithms',
17+
field=django.contrib.postgres.fields.ArrayField(base_field=models.JSONField(), blank=True, default=list, null=True, size=None),
18+
),
19+
]
Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
# Generated by Django 4.2.16 on 2026-02-06 06:30
2+
3+
from django.db import migrations
4+
5+
def update_algorithms(apps, schema_editor):
6+
MapProject = apps.get_model('map_projects', 'MapProject')
7+
for project in MapProject.objects.filter():
8+
algos = []
9+
if project.matching_algorithm == 'es':
10+
algos.append({
11+
'id': 'ocl-search',
12+
'name': 'OCL Search Algorithm',
13+
'type': 'ocl-search',
14+
'provider': 'ocl',
15+
'order': 1,
16+
'batch_size': 50,
17+
'concurrent_requests': 2
18+
})
19+
if project.matching_algorithm == 'llm':
20+
algos.append({
21+
'id': 'ocl-semantic',
22+
'name': 'OCL Semantic Algorithm',
23+
'type': 'ocl-semantic',
24+
'provider': 'ocl',
25+
'order': 1,
26+
'batch_size': 10,
27+
'concurrent_requests': 2,
28+
'query_params': {
29+
'semantic': True
30+
}
31+
})
32+
if project.matching_algorithm == 'custom' and project.match_api_url:
33+
algos.append({
34+
'id': 'custom',
35+
'name': 'Custom Algorithm',
36+
'type': 'custom',
37+
'provider': 'external',
38+
'order': 1,
39+
'batch_size': project.batch_size,
40+
'url': project.match_api_url,
41+
'token': project.match_api_token,
42+
'concurrent_requests': 1,
43+
})
44+
if project.bridge_enabled:
45+
algos.append({
46+
'id': 'ocl-ciel-bridge',
47+
'name': 'OCL CIEL Bridge Terminology',
48+
'type': 'ocl-ciel-bridge',
49+
'provider': 'ocl',
50+
'order': 2,
51+
'batch_size': 10,
52+
'concurrent_requests': 2,
53+
'query_params': {
54+
'semantic': True
55+
},
56+
'target_repo_url': '/orgs/CIEL/sources/CIEL/'
57+
})
58+
if project.scispacy_enabled:
59+
algos.append({
60+
'id': 'ocl-scispacy-loinc',
61+
'name': 'OCL ScispaCy LOINC Algorithm',
62+
'type': 'ocl-scispacy',
63+
'provider': 'ocl',
64+
'order': 3,
65+
'batch_size': 2,
66+
'concurrent_requests': 1,
67+
})
68+
if algos:
69+
project.algorithms = algos
70+
project.save(update_fields=['algorithms'])
71+
72+
73+
class Migration(migrations.Migration):
74+
75+
dependencies = [
76+
('map_projects', '0024_mapproject_algorithms'),
77+
]
78+
79+
operations = [
80+
migrations.RunPython(update_algorithms),
81+
]
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
# Generated by Django 4.2.16 on 2026-02-11 12:09
2+
3+
from django.db import migrations
4+
5+
6+
class Migration(migrations.Migration):
7+
8+
dependencies = [
9+
('map_projects', '0025_auto_20260206_0630'),
10+
]
11+
12+
operations = [
13+
migrations.RemoveField(
14+
model_name='mapproject',
15+
name='batch_size',
16+
),
17+
migrations.RemoveField(
18+
model_name='mapproject',
19+
name='bridge_enabled',
20+
),
21+
migrations.RemoveField(
22+
model_name='mapproject',
23+
name='match_api_token',
24+
),
25+
migrations.RemoveField(
26+
model_name='mapproject',
27+
name='match_api_url',
28+
),
29+
migrations.RemoveField(
30+
model_name='mapproject',
31+
name='matching_algorithm',
32+
),
33+
migrations.RemoveField(
34+
model_name='mapproject',
35+
name='scispacy_enabled',
36+
),
37+
]

core/map_projects/models.py

Lines changed: 2 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -30,19 +30,12 @@ class MapProject(BaseModel):
3030
matches = ArrayField(models.JSONField(), default=list, null=True, blank=True)
3131
columns = ArrayField(models.JSONField(), default=list)
3232
target_repo_url = models.TextField(null=True, blank=True)
33-
matching_algorithm = models.CharField(max_length=100, null=True, blank=True)
33+
algorithms = ArrayField(models.JSONField(), default=list, null=True, blank=True)
3434
include_retired = models.BooleanField(default=False)
3535
logs = models.JSONField(default=dict, null=True, blank=True)
3636
score_configuration = models.JSONField(default=default_score_configuration, null=True, blank=True)
3737
filters = models.JSONField(default=dict, null=True, blank=True)
3838
candidates = models.JSONField(default=dict, null=True, blank=True)
39-
bridge_enabled = models.BooleanField(default=False)
40-
scispacy_enabled = models.BooleanField(default=False)
41-
42-
# Custom API
43-
match_api_url = models.TextField(null=True, blank=True)
44-
match_api_token = models.TextField(null=True, blank=True)
45-
batch_size = models.IntegerField(null=True, blank=True, default=BATCH_SIZE)
4639

4740
class Meta:
4841
db_table = 'map_projects'
@@ -172,6 +165,7 @@ def format_request_data(cls, data, parent_resource=None):
172165
cls.format_json(new_data, 'score_configuration')
173166
cls.format_json(new_data, 'filters')
174167
cls.format_json(new_data, 'candidates')
168+
cls.format_json(new_data, 'algorithms')
175169

176170
if parent_resource:
177171
new_data[parent_resource.resource_type.lower() + '_id'] = parent_resource.id
@@ -195,8 +189,6 @@ def soft_delete(self):
195189

196190
def clean(self):
197191
self.clean_filters()
198-
if not self.batch_size:
199-
self.batch_size = self.BATCH_SIZE
200192
if not self.include_retired:
201193
self.include_retired = False
202194
if self.matches:

core/map_projects/serializers.py

Lines changed: 6 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -21,9 +21,8 @@ class Meta:
2121
'id', 'name', 'input_file_name', 'matches', 'columns',
2222
'created_by', 'updated_by', 'created_at', 'updated_at', 'url', 'is_active',
2323
'public_access', 'file', 'user_id', 'organization_id', 'description',
24-
'target_repo_url', 'matching_algorithm', 'include_retired', 'score_configuration',
25-
'match_api_url', 'match_api_token', 'batch_size', 'filters', 'candidates',
26-
'bridge_enabled', 'scispacy_enabled'
24+
'target_repo_url', 'include_retired', 'score_configuration',
25+
'filters', 'candidates', 'algorithms'
2726
]
2827

2928
def prepare_object(self, validated_data, instance=None, file=None):
@@ -36,9 +35,8 @@ def prepare_object(self, validated_data, instance=None, file=None):
3635
if columns is not False:
3736
instance.columns = columns
3837
for attr in [
39-
'name', 'description', 'extras', 'target_repo_url', 'matching_algorithm', 'include_retired',
40-
'score_configuration', 'match_api_url', 'match_api_token', 'batch_size', 'filters', 'candidates',
41-
'bridge_enabled', 'scispacy_enabled'
38+
'name', 'description', 'extras', 'target_repo_url', 'include_retired',
39+
'score_configuration', 'filters', 'candidates', 'algorithms'
4240
]:
4341
setattr(instance, attr, validated_data.get(attr, get(instance, attr)))
4442
if not instance.id:
@@ -110,9 +108,8 @@ class Meta:
110108
'id', 'name', 'input_file_name',
111109
'created_by', 'updated_by', 'created_at', 'updated_at', 'url', 'is_active',
112110
'owner', 'owner_type', 'owner_url', 'public_access',
113-
'target_repo_url', 'matching_algorithm', 'summary', 'logs', 'include_retired',
114-
'score_configuration', 'match_api_url', 'match_api_token', 'batch_size', 'filters', 'candidates',
115-
'bridge_enabled', 'scispacy_enabled'
111+
'target_repo_url', 'summary', 'logs', 'include_retired',
112+
'score_configuration', 'filters', 'candidates', 'algorithms'
116113
]
117114

118115
def __init__(self, *args, **kwargs):

0 commit comments

Comments
 (0)