Free lesson · GenAI Platform Engineering

સર્ચ અને ફિલ્ટરિંગ સાથે service catalog REST API બનાવો

service catalog ને platform consumers માટે ઉપલબ્ધ કરાવતું API layer બનાવો. સર્ચ, category દ્વારા ફિલ્ટરિંગ અને versioned catalog responses અમલમાં મૂકો.

Course: AI Developer Platform Engineering · Chapter 1 · Internal Developer Platform Vision

Free to read — no subscription required.

પરિચય

જ્યારે તમે સર્વિસ કેટલોગ પ્રકાશિત કરો છો પણ ઉપભોક્તાઓને તેને ક્વેરી કરવાની કોઈ પ્રોગ્રામેટિક રીત આપતા નથી, ત્યારે ટીમો Git રેપોમાં કાચું YAML વાંચવા, Slack સંદેશાઓના સ્ક્રીનશોટ લેવા, અથવા ટિકિટમાં પ્લેટફોર્મ ટીમને "આપણે કયા વેક્ટર ડેટાબેઝ ઓફર કરીએ છીએ?" એવું પૂછવા તરફ વળે છે. કેટલોગ ડેટા અસ્તિત્વમાં છે, પણ તે શોધી શકાય તેવો નથી—એન્જિનિયરો માનવ હસ્તક્ષેપ વિના "team-beta ની માલિકીની દરેક GPU-આધારિત મોડેલ-સર્વિંગ એન્ટ્રી મને બતાવો, સૌથી નવું વર્ઝન પહેલાં" એવા પ્રશ્નનો જવાબ મેળવી શકતા નથી. API સ્તર આ અંતર પૂરે છે: તે કેટલોગને HTTP પર સ્ટ્રક્ચર્ડ સર્ચ, કેટેગરી ફિલ્ટરિંગ, પેજિનેશન અને સ્પષ્ટ રિસ્પોન્સ વર્ઝન સાથે ઉપલબ્ધ કરે છે, જેથી ડેવલપર પોર્ટલ, CLI અને CI પાઇપલાઇન બધા એક જ કોન્ટ્રાક્ટનો ઉપયોગ કરી શકે. આ પાઠના અંતે, તમે ઉપભોક્તાના ઇનપુટને માન્ય કરતી ક્વેરી અને રિસ્પોન્સ સ્કીમા વ્યાખ્યાયિત કરી શકશો, કેટલોગ સ્ટોર પર ચાલતું ફુલ-ટેક્સ્ટ સર્ચ અને કેટેગરી ફિલ્ટર અમલમાં મૂકી શકશો, અને પરિણામોને એક વર્ઝન્ડ એન્વલપમાં લપેટી શકશો જે તમને હાલના ક્લાયન્ટ્સને તોડ્યા વિના પેલોડનો આકાર વિકસાવવા દે છે.

મુખ્ય પરિભાષા

  • Catalog API: HTTP ઇન્ટરફેસ જે સર્વિસ કેટલોગ પર વાંચન કામગીરીઓ—લિસ્ટિંગ, સર્ચિંગ, ફિલ્ટરિંગ અને વ્યક્તિગત એન્ટ્રી મેળવવી—પ્લેટફોર્મ ઉપભોક્તાઓ માટે ઉપલબ્ધ કરે છે.
  • Query Parameter Model: એક માન્ય કરેલી સ્કીમા (CatalogQuery) જે URL ક્વેરી સ્ટ્રિંગ દલીલોને ટાઇપ કરેલા ફીલ્ડ સાથે બાંધે છે, અને કોઈપણ સ્ટોર એક્સેસ પહેલાં ખોટી રચનાવાળી વિનંતીઓને નકારે છે.
  • Response Envelope: એક રેપર ઓબ્જેક્ટ (CatalogListResponse) જે પરિણામ આઇટમો સાથે કુલ ગણતરી, પેજિનેશન કર્સર અને API વર્ઝન જેવા મેટાડેટા વહન કરે છે.
  • API Versioning: દરેક રિસ્પોન્સમાં સ્પષ્ટ api_version ફીલ્ડ સમાવવું, જેથી ઉપભોક્તાઓ ચૂપચાપ તૂટવાને બદલે સ્કીમા બદલાવોને શોધી શકે અને તેને અનુકૂળ થઈ શકે.
  • Category Filter: એક સર્વર-સાઇડ પ્રેડિકેટ જે પરિણામોને ServiceCategory સાથે મેળ ખાતી એન્ટ્રીઓ સુધી સંકુચિત કરે છે, અને ગણતરીઓ સચોટ રહે તે માટે પેજિનેશન પહેલાં લાગુ થાય છે.

વિભાવનાઓ

હવે આપણી પાસે ઉપલબ્ધ કરવા માટે કેટલોગ ડેટા મોડેલ છે, ત્યારે API સ્તર પ્લેટફોર્મ ઉપભોક્તાઓ અને અંતર્ગત એન્ટ્રી સ્ટોર વચ્ચે બેસે છે, અને ઢીલા-ટાઇપવાળી HTTP ક્વેરી સ્ટ્રિંગ્સને માન્ય કરેલા, ફિલ્ટર કરેલા, વર્ઝન્ડ રિસ્પોન્સમાં રૂપાંતરિત કરે છે. એક વિનંતી ચાર તબક્કામાંથી વહે છે: ઇનપુટ બાઇન્ડિંગ, ફિલ્ટરિંગ, પેજિનેશન અને એન્વલપ નિર્માણ. દરેક તબક્કાની એક જ જવાબદારી છે, અને તેમને અલગ રાખવાથી જ સર્ચ એન્ડપોઇન્ટ ટેસ્ટ કરી શકાય તેવો અને રિસ્પોન્સનો આકાર વિકસાવી શકાય તેવો બને છે.

Loading diagram...

ઇનપુટ બાઇન્ડિંગ તબક્કો ?q=qdrant&category=vector-db&limit=20&offset=0 ને CatalogQuery ઇન્સ્ટન્સ પર મેપ કરે છે. ટાઇપ કરેલા મોડેલ દ્વારા બાઇન્ડિંગ કરવાનો અર્થ એ છે કે અમાન્ય limit (નકારાત્મક, અથવા મર્યાદાથી ઉપર) આપમેળે 422 સાથે નકારાય છે—એન્ડપોઇન્ટ બોડી ખરાબ ઇનપુટ સામે કદી ચાલતી નથી. ફિલ્ટરિંગ તબક્કો બે સ્વતંત્ર પ્રેડિકેટ લાગુ કરે છે: q શબ્દ માટે એન્ટ્રીના name અને description સામે કેસ-અસંવેદનશીલ સબસ્ટ્રિંગ મેચ, અને category માટે ચોક્કસ service_type મેચ. બંને વૈકલ્પિક છે; કોઈ એકને છોડી દેવાથી ભૂલ થવાને બદલે પરિણામ સમૂહ વિસ્તરે છે.

છેલ્લા બે તબક્કાઓ વચ્ચેનો ક્રમ મહત્વનો છે. ફિલ્ટરિંગ પેજિનેશન પહેલાં પૂર્ણ થવું જોઈએ, જેથી total મેળ ખાતી એન્ટ્રીઓની ગણતરી દર્શાવે, બધી એન્ટ્રીઓની નહીં. જો તમે પહેલા પેજિનેટ કરો અને પછી પેજને ફિલ્ટર કરો, તો સર્ચનું બીજું પેજ એ મેચો ચૂપચાપ છોડી દે છે જે યોગાનુયોગ પહેલા પેજ પર આવી ગઈ હતી, અને total અર્થહીન બને છે. સમગ્ર સમૂહ પર apply_filters ચલાવવું, ફિલ્ટર કરેલી લંબાઈથી total ગણવું, અને તે પછી જ paginate સાથે સ્લાઇસ કરવું—આ પેજિનેશન મેટાડેટાને પ્રામાણિક રાખે છે.

રિસ્પોન્સ એન્વલપ એ છે જ્યાં વર્ઝનિંગ રહે છે. માત્ર JSON એરે પરત કરવાને બદલે, list_services એક CatalogListResponse પરત કરે છે જે api_version, items, total, limit અને offset વહન કરે છે. ઉપભોક્તાઓ api_version વાંચીને નક્કી કરે છે કે તેઓ પેલોડ સમજે છે કે નહીં. જ્યારે તમે પછીથી કોઈ ફીલ્ડ ઉમેરો—કહો કે deprecation_notice—ત્યારે api_version "v1" પર પિન કરેલા જૂના ક્લાયન્ટ્સ કામ કરતા રહે છે, કારણ કે એક વર્ઝનની અંદર ઉમેરાત્મક બદલાવો સુરક્ષિત છે, અને બ્રેકિંગ બદલાવ વર્ઝન વધારે છે જેથી ક્લાયન્ટ્સ તેના પર બ્રાન્ચ કરી શકે. આ એ જ શિસ્ત છે જે તમે કેટલોગ એન્ટ્રીઓ પર પોતે લાગુ કરો છો, ટ્રાન્સપોર્ટ સ્તર સુધી વિસ્તારેલી.

કોડ વોકથ્રુ

ચાર-તબક્કાના વિનંતી પ્રવાહની સમીક્ષા કર્યા પછી, નીચેનું અમલીકરણ તેને બે ભાગોમાં એન્કોડ કરે છે: HTTP કોન્ટ્રાક્ટને બાંધતી અને માન્ય કરતી વિનંતી/રિસ્પોન્સ સ્કીમા, અને FastAPI રાઉટર જે સર્ચ, ફિલ્ટરિંગ અને પેજિનેશનને બે એન્ડપોઇન્ટમાં જોડે છે. પહેલો બ્લોક ServiceCategory, CatalogQuery ઇનપુટ મોડેલ, પ્રતિ-આઇટમ CatalogItemResponse, અને વર્ઝન્ડ CatalogListResponse એન્વલપ વ્યાખ્યાયિત કરે છે—દરેક ફીલ્ડ એવી રીતે બંધાયેલું છે કે ખોટી રચનાવાળી વિનંતીઓ હેન્ડલરની ઊંડાઈમાં નહીં પણ બાઇન્ડિંગ સમયે જ નિષ્ફળ થાય.

Code snippetpython
1from pydantic import BaseModel, Field 2from enum import Enum 3from typing import Optional 4 5CATALOG_API_VERSION = "v1" 6 7class ServiceCategory(str, Enum): 8 MODEL_SERVING = "model-serving" 9 TRAINING_JOB = "training-job" 10 VECTOR_DB = "vector-db" 11 FEATURE_STORE = "feature-store" 12 MONITORING = "monitoring" 13 14class CatalogQuery(BaseModel): 15 q: Optional[str] = Field(default=None, max_length=128) 16 category: Optional[ServiceCategory] = None 17 limit: int = Field(default=25, ge=1, le=100) 18 offset: int = Field(default=0, ge=0) 19 20class CatalogItemResponse(BaseModel): 21 service_id: str 22 name: str 23 service_type: ServiceCategory 24 version: str 25 owner_team: str 26 description: str 27 deprecated: bool 28 29class CatalogListResponse(BaseModel): 30 api_version: str = CATALOG_API_VERSION 31 total: int 32 limit: int 33 offset: int 34 items: list[CatalogItemResponse]
  • લાઇન 6-12: ServiceCategory કેટલોગની સર્વિસ-ટાઇપ વર્ગીકરણ પદ્ધતિના જ kebab-case મૂલ્યોનો પુનઃઉપયોગ કરે છે, જેથી વાસ્તવિક કેટેગરી ન હોય તેવું category ક્વેરી પેરામીટર બાઇન્ડિંગ સમયે જ નકારાય—હેન્ડલરની અંદર તેને હાથે માન્ય કરવાની જરૂર નથી.
  • લાઇન 14-18: CatalogQuery limit ને [1, 100] સુધી અને offset ને ≥ 0 સુધી મર્યાદિત કરે છે. limit=5000 માંગતા ક્લાયન્ટને 422 મળે છે, જે સ્ટોરને અમર્યાદિત સ્કેનથી બચાવે છે; બંને સર્ચ ફીલ્ડ ડિફોલ્ટ None છે, જેથી દલીલ વગરની વિનંતી બધાનું પહેલું પેજ પરત કરે.
  • લાઇન 28-33: CatalogListResponse api_version ને ડિફોલ્ટ CATALOG_API_VERSION પર રાખે છે, જેથી દરેક રિસ્પોન્સ સ્વ-વર્ણનાત્મક હોય; total items ની બાજુમાં બેસે છે જેથી ઉપભોક્તાઓ બીજા કોલ વિના ગણી શકે કે કેટલાં પેજ બાકી છે.

બીજો બ્લોક ફિલ્ટરિંગ અને પેજિનેશનના શુદ્ધ ફંક્શન્સ તથા બે એન્ડપોઇન્ટ અમલમાં મૂકે છે. apply_filters સંપૂર્ણ એન્ટ્રી સમૂહ પર બંને પ્રેડિકેટ ચલાવે છે; paginate ફિલ્ટર કરેલી યાદીને સ્લાઇસ કરે છે; list_services તેમને જોડે છે અને એન્વલપ બનાવે છે; get_service એક-એન્ટ્રી લુકઅપ સંભાળે છે અને service_id અજાણ્યું હોય ત્યારે 404 raise કરે છે.

Code snippetpython
1from fastapi import APIRouter, Depends, HTTPException 2 3router = APIRouter(prefix="/catalog", tags=["catalog"]) 4 5def apply_filters(entries: list, query: CatalogQuery) -> list: 6 results = entries 7 if query.category is not None: 8 results = [e for e in results if e.service_type == query.category] 9 if query.q: 10 term = query.q.lower() 11 results = [ 12 e for e in results 13 if term in e.name.lower() or term in e.description.lower() 14 ] 15 return results 16 17def paginate(entries: list, limit: int, offset: int) -> list: 18 return entries[offset : offset + limit] 19 20@router.get("", response_model=CatalogListResponse) 21def list_services(query: CatalogQuery = Depends(), store=Depends(get_catalog_store)): 22 matched = apply_filters(store.all_entries(), query) 23 page = paginate(matched, query.limit, query.offset) 24 return CatalogListResponse( 25 total=len(matched), 26 limit=query.limit, 27 offset=query.offset, 28 items=[CatalogItemResponse(**e.model_dump()) for e in page], 29 ) 30 31@router.get("/{service_id}", response_model=CatalogItemResponse) 32def get_service(service_id: str, store=Depends(get_catalog_store)): 33 entry = store.get(service_id) 34 if entry is None: 35 raise HTTPException(status_code=404, detail=f"unknown service_id: {service_id}") 36 return CatalogItemResponse(**entry.model_dump())
  • લાઇન 5-15: apply_filters પહેલાં કેટેગરી પ્રેડિકેટ (સસ્તી ચોક્કસ મેચ) લાગુ કરે છે, પછી સબસ્ટ્રિંગ સર્ચ; બંને is not None / સત્યતા-તપાસથી સુરક્ષિત છે, જેથી છોડી દેવાયેલું પેરામીટર કંઈ ન કરતી કામગીરી બને જે પરિણામો વિસ્તારે, શૂન્ય સુધી ફિલ્ટર ન કરે.
  • લાઇન 22-30: list_services સમગ્ર સમૂહ પર matched ગણે છે, સ્લાઇસ કરતાં પહેલાં len(matched) થી total મેળવે છે, પછી પેજિનેટ કરે છે—આ ખાતરી આપે છે કે એન્વલપનું total મેચોની ગણતરી કરે છે, કાચા કેટલોગના કદની નહીં.
  • લાઇન 33-38: get_service એક એન્ટ્રી પરત કરે છે અથવા 404 સાથે HTTPException raise કરે છે; None પરત કરવાથી FastAPI null બોડી સિરિયલાઇઝ કરી દેત, તેથી સ્પષ્ટ raise જ ઉપભોક્તાઓને કાર્યક્ષમ ભૂલ આપે છે.

ચકાસણી માટે GET /catalog?category=vector-db&q=qdrant&limit=5 જારી કરો—રિસ્પોન્સમાં api_version: "v1", મેળ ખાતી vector-db એન્ટ્રીઓ જેમના name અથવા description માં "qdrant" હોય તેની સંખ્યા જેટલું total, અને વધુમાં વધુ પાંચ items હોવા જોઈએ; પછી GET /catalog/does-not-exist એ unknown service_id વિગત સાથે 404 પરત કરવું જોઈએ.

શિસ્ત-વિશિષ્ટ ઉપયોગ

શું કરવું અને શું ન કરવું

ઉપર ક્વેરી સ્કીમા, ફિલ્ટર-પછી-પેજિનેટ પાઇપલાઇન અને વર્ઝન્ડ એન્વલપમાંથી પસાર થયા બાદ, નીચેના આદેશો API-કોન્ટ્રાક્ટ અને સર્ચ-સચોટતાની પેટર્નને એવા નિયમોમાં સંક્ષિપ્ત કરે છે જે તમે તમારા પોતાના કેટલોગ એન્ડપોઇન્ટ બનાવતી વખતે સીધા લાગુ કરી શકો.

શું કરવું

  1. ક્વેરી સ્ટ્રિંગ્સને Depends() સાથે CatalogQuery મોડેલ દ્વારા બાંધો — Field મર્યાદાઓ (limit [1, 100] માં, offset ≥ 0, category એક ServiceCategory તરીકે) list_services ચાલે તે પહેલાં ખોટી રચનાવાળી વિનંતીઓને 422 સાથે નકારે છે, જેથી કોઈ હેન્ડલર કોડ કદી અમર્યાદિત limit અથવા અજાણી કેટેગરી સ્ટ્રિંગ સામે ચાલતો નથી.
  2. apply_filters સંપૂર્ણ એન્ટ્રી સમૂહ પર ચલાવો અને paginate કોલ કરતાં પહેલાં len(matched) થી total મેળવો — ફિલ્ટર કરેલી પણ સ્લાઇસ ન કરેલી યાદી પર ગણતરી કરવાથી CatalogListResponse.total ફીલ્ડ પ્રામાણિક રહે છે, જેથી ઉપભોક્તાઓ મેચો ચૂપચાપ ગુમાવ્યા વિના સર્ચ પરિણામોમાંથી પેજ-દર-પેજ પસાર થઈ શકે.
  3. દરેક રિસ્પોન્સ પર CATALOG_API_VERSION માંથી api_version મૂકો — સ્વ-વર્ણનાત્મક એન્વલપ પોર્ટલ અને CI ક્લાયન્ટ્સને વર્ઝન પર બ્રાન્ચ કરવા દે છે, અને તમને "v1" ની અંદર ઉમેરાત્મક રીતે ફીલ્ડ ઉમેરવા દે છે, જ્યારે બ્રેકિંગ પેલોડ બદલાવો માટે વર્ઝન વધારો અનામત રાખે છે.

શું ન કરવું

  1. ફિલ્ટરિંગ પહેલાં પેજિનેટ ન કરો — પહેલાં store.all_entries() ને સ્લાઇસ કરવું અને પછી પેજ પર apply_filters ચલાવવું total ને અર્થહીન બનાવે છે અને વર્તમાન વિન્ડો બહાર આવતી મેચો છોડી દે છે; પાઇપલાઇનનો ક્રમ (apply_filters → paginate) જ સાચી ગણતરીઓ અને સંપૂર્ણ પરિણામ સમૂહની ખાતરી આપે છે.
  2. list_services માંથી માત્ર યાદી પરત ન કરો — CatalogListResponse એન્વલપ છોડી દેવાથી api_version, total અને offset નીકળી જાય છે, અને ઉપભોક્તાઓ પાસે સ્કીમા બદલાવો શોધવાની કે પેજિનેશન ચલાવવાની કોઈ રીત રહેતી નથી—જે બરાબર એ જ શોધક્ષમતાનું અંતર છે જે API પૂરવા માટે બન્યું છે.
  3. ખૂટતા service_id માટે get_service માંથી return None ન કરો — null બોડી null સાથે 200 તરીકે સિરિયલાઇઝ થાય છે, જે ભૂલ છુપાવે છે; HTTPException(status_code=404, ...) raise કરવું ઉપભોક્તાઓને કાર્યક્ષમ, યોગ્ય કોડવાળી નિષ્ફળતા આપે છે જેના પર તેઓ બ્રાન્ચ કરી શકે.

3 hands-on labs come with this lesson — real code, in a cloud IDE. Create a free account to run them. No card.

Free account · no card · straight to the labs

Or get the full path — from

Listen to this lesson

Audio overviews of this lesson's labs and its chapter, from GenBodha Bytes.

More free lessons in AI Developer Platform Engineering

All free lessons in GenAI Platform Engineering →