Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 34 additions & 0 deletions core/common/swagger_parameters.py
Original file line number Diff line number Diff line change
Expand Up @@ -202,3 +202,37 @@
'start_date', openapi.IN_QUERY, type=openapi.TYPE_STRING, format='YYYY-MM-DD', required=False,
description='filter by start date of tasks'
)

# $match params
match_semantic_param = openapi.Parameter(
'semantic', openapi.IN_QUERY, type=openapi.TYPE_BOOLEAN, default=False,
description='Use semantic (LM-based) matching algorithm'
)
match_best_match_param = openapi.Parameter(
'bestMatch', openapi.IN_QUERY, type=openapi.TYPE_BOOLEAN, default=False,
description='Apply minimum score threshold, filtering out low-quality matches'
)
match_num_candidates_param = openapi.Parameter(
'numCandidates', openapi.IN_QUERY, type=openapi.TYPE_INTEGER, default=3000,
description='Number of approximate nearest neighbor candidates (semantic only). Max: 3000'
)
match_k_nearest_param = openapi.Parameter(
'kNearest', openapi.IN_QUERY, type=openapi.TYPE_INTEGER, default=100,
description='Number of nearest neighbors to return from vector search (semantic only). Max: 100'
)
match_brief_param = openapi.Parameter(
'brief', openapi.IN_QUERY, type=openapi.TYPE_BOOLEAN, default=False,
description='Return minimal concept fields in results'
)
match_encoder_model_param = openapi.Parameter(
'encoder_model', openapi.IN_QUERY, type=openapi.TYPE_STRING,
description='Custom encoder model name for semantic vector search'
)
match_reranker_param = openapi.Parameter(
'reranker', openapi.IN_QUERY, type=openapi.TYPE_BOOLEAN, default=False,
description='Enable cross-encoder reranking of results (semantic only)'
)
match_offset_param = openapi.Parameter(
'offset', openapi.IN_QUERY, type=openapi.TYPE_INTEGER, default=0,
description='Number of results to skip per row'
)
48 changes: 47 additions & 1 deletion core/concepts/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
from django.conf import settings
from django.db.models import F
from django.http import Http404
from drf_yasg import openapi
from drf_yasg.utils import swagger_auto_schema
from pydash import get, compact
from rest_framework import status
Expand All @@ -28,7 +29,9 @@
compress_header, include_source_versions_param, include_collection_versions_param, cascade_method_param,
cascade_map_types_param, cascade_exclude_map_types_param, cascade_hierarchy_param, cascade_mappings_param,
cascade_levels_param, cascade_direction_param, cascade_view_hierarchy, return_map_types_param,
omit_if_exists_in_param, equivalency_map_types_param, search_from_latest_repo_header)
omit_if_exists_in_param, equivalency_map_types_param, search_from_latest_repo_header,
match_semantic_param, match_best_match_param, match_num_candidates_param, match_k_nearest_param,
match_brief_param, match_encoder_model_param, match_reranker_param, match_offset_param)
from core.common.tasks import delete_concept, make_hierarchy
from core.common.throttling import ThrottleUtil
from core.common.utils import (to_parent_uri_from_kwargs, generate_temp_version, get_truthy_values, to_int,
Expand Down Expand Up @@ -933,6 +936,49 @@ def get_repo_params(is_semantic, target_repo_params, target_repo_url):
raise Http400(f'Unable to resolve "target_repo_url": "{target_repo_url}"')
return repo_params

@swagger_auto_schema(
operation_description='Find matching concepts across repositories using structured input data.',
operation_summary='$match - Find matching concepts',
manual_parameters=[
verbose_param, include_retired_param, limit_param, page_param, match_offset_param,
match_semantic_param, match_best_match_param, match_num_candidates_param,
match_k_nearest_param, match_brief_param, match_encoder_model_param, match_reranker_param,
],
request_body=openapi.Schema(
type=openapi.TYPE_OBJECT,
required=['rows'],
properties={
'target_repo_url': openapi.Schema(
type=openapi.TYPE_STRING,
description='Repository URL to match against. Either target_repo_url or target_repo is required.'
),
'target_repo': openapi.Schema(
type=openapi.TYPE_OBJECT,
description='Alternative to target_repo_url. Object with owner, source, source_version, '
'owner_type fields.'
),
'rows': openapi.Schema(
type=openapi.TYPE_ARRAY,
items=openapi.Schema(type=openapi.TYPE_OBJECT),
description='List of concept-like key-value pairs to match.'
),
'map_config': openapi.Schema(
type=openapi.TYPE_ARRAY,
items=openapi.Schema(type=openapi.TYPE_OBJECT),
description='Optional list configuring mapping logic per row.'
),
'filter': openapi.Schema(
type=openapi.TYPE_OBJECT,
description='Filtering criteria including locale and faceted filters.'
),
}
),
responses={
200: 'List of matched results per input row',
400: 'Missing required parameters (rows, target_repo_url/target_repo)',
403: 'User not approved for $match or on waitlist',
}
)
def post(self, request, **kwargs): # pylint: disable=unused-argument
user = self.request.user
if user.is_mapper_waitlisted or not user.is_mapper_approved:
Expand Down
Loading