Skip to content

Implement API functions for architecture and services#689

Draft
yussufsh wants to merge 1 commit intoIBM:mainfrom
yussufsh:apis_new
Draft

Implement API functions for architecture and services#689
yussufsh wants to merge 1 commit intoIBM:mainfrom
yussufsh:apis_new

Conversation

@yussufsh
Copy link
Copy Markdown
Member

This implements catalog API system for managing AI service architectures and services. The following APIs are implemented with swagger docs.

GET /architectures - List all architectures (summary view)
GET /architectures/:id - Get architecture details
GET /services - List deployable services (excludes dependency-only)
GET /services/:id - Get service details

Key Changes:

  1. New Core Catalog functions - catalog.go
  2. API Server Implementation
  3. Type Definitions - Architecture and Service types for detail views
  4. Swagger Documentation (Auto-generated by Bob)
  5. Template Provider Enhancements

Signed-off-by: Yussuf Shaikh <yussuf.shaikh1@ibm.com>
@yussufsh
Copy link
Copy Markdown
Member Author

=== API 1: List Architectures ===

[
  {
    "id": "rag",
    "name": "Digital Assistant",
    "description": "Enable digital assistants using Retrieval-Augmented Generation (RAG), including AI services that query a managed knowledge base to answer questions from custom documents and data.",
    "certified_by": "IBM",
    "services": [
      "chat",
      "digitize",
      "summarize"
    ]
  }
]

=== API 2: Get Architecture Details (rag) ===

{
  "id": "rag",
  "name": "Digital Assistant",
  "description": "Enable digital assistants using Retrieval-Augmented Generation (RAG), including AI services that query a managed knowledge base to answer questions from custom documents and data.",
  "version": "1.0.0",
  "type": "architecture",
  "certified_by": "IBM",
  "runtimes": [
    "podman"
  ],
  "services": [
    {
      "id": "chat",
      "version": ">=1.0.0"
    },
    {
      "id": "digitize",
      "version": ">=1.0.0"
    },
    {
      "id": "summarize",
      "version": ">=1.0.0",
      "optional": true
    }
  ],
  "links": {
    "demo": "https://example.com/demo/rag",
    "code": "https://github.com/project-ai-services/spyre-rag",
    "documentation": "https://docs.example.com/rag"
  }
}

@yussufsh
Copy link
Copy Markdown
Member Author

=== API 3: List Services ===

[
  {
    "id": "chat",
    "name": "Question and Answer",
    "description": "Answer questions in natural language by sourcing general & domain-specific knowledge",
    "certified_by": "IBM",
    "architectures": [
      "rag"
    ]
  },
  {
    "id": "digitize",
    "name": "Digitize Documents",
    "description": "Transforms documents such as manuals, invoices, and more into texts",
    "certified_by": "IBM",
    "architectures": [
      "rag"
    ]
  },
  {
    "id": "summarize",
    "name": "Summarize",
    "description": "Consolidates input text into a brief statement of main points",
    "certified_by": "IBM",
    "architectures": [
      "rag"
    ]
  }
]

=== API 4: Get Service Details (chat) ===

{
  "id": "chat",
  "name": "Question and Answer",
  "description": "Answer questions in natural language by sourcing general & domain-specific knowledge",
  "type": "service",
  "certified_by": "IBM",
  "architectures": [
    "rag"
  ],
  "dependencies": [
    {
      "id": "opensearch",
      "version": ">=1.0.0"
    },
    {
      "id": "embedding",
      "version": ">=1.0.0"
    },
    {
      "id": "instruct",
      "version": ">=1.0.0"
    },
    {
      "id": "reranker",
      "version": ">=1.0.0"
    }
  ]
}

Comment on lines +1 to +5
package handlers

import (
"encoding/json"
"net/http"
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I dont think we need test file as we are not writing any UTs now. Can we remove?

Version string `yaml:"version" json:"version"`
Type string `yaml:"type" json:"type"` // "architecture"
CertifiedBy string `yaml:"certified_by" json:"certified_by"`
Runtimes []string `yaml:"runtimes" json:"runtimes"`
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We do not require runtimes

Description string `yaml:"description" json:"description"`
Type string `yaml:"type" json:"type"` // "service"
CertifiedBy string `yaml:"certified_by" json:"certified_by"`
DependencyOnly bool `yaml:"dependency_only,omitempty" json:"dependency_only,omitempty"`
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we need this dependency_only in response?. I thought by default we are filtering out the Infra services like Opensearch, models

Copy link
Copy Markdown
Member

@mayuka-c mayuka-c left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here are my initial comments
I will take a look at the internal logic sometime later as there are lot of things :)

for _, id := range serviceIDs {
service, err := LoadService(id)
if err != nil {
// Log error but continue with other services
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we log the error to know the reason why load failed as I see we are simply doing continue


// GetDeploymentOrder returns services grouped into deployment layers
// Services in the same layer can be deployed in parallel
func GetDeploymentOrder(serviceIDs []string) ([][]string, error) {
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we add some example on how the resultant of this method look like as it is 2D slice. Will be easier to know how it looks

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

+1

for _, id := range archIDs {
arch, err := LoadArchitecture(id)
if err != nil {
// Log error but continue with other architectures
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we are not logging error here
maybe collect all errors here and print after loop ends?

Comment on lines +158 to +160
if visited[serviceID] {
return nil
}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can you help me understand this part please?

since we are returning nil here, wouldnt it pass if graph has cyclic dependency?
Suppose there are 2 services; S1 and S2
S1 depends on S2
S2 depends on S1

S1 -> not visited -> mark visited
S2 -> not visited -> mark visited
S1 -> visited -> return nil (skipping the cycle here)
append S2 -> [S2]
append S1 -> [S2, S1]

is the aim here to find all unique transitive deps (and ignoring cycles), or to prevent cycles?


// GetDeploymentOrder returns services grouped into deployment layers
// Services in the same layer can be deployed in parallel
func GetDeploymentOrder(serviceIDs []string) ([][]string, error) {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

+1

Comment on lines +38 to +63
func ToServiceSummary(service *types.Service) types.ServiceSummary {
return types.ServiceSummary{
ID: service.ID,
Name: service.Name,
Description: service.Description,
CertifiedBy: service.CertifiedBy,
Architectures: service.Architectures,
}
}

// ToArchitectureSummary converts an Architecture to ArchitectureSummary
func ToArchitectureSummary(arch *types.Architecture) types.ArchitectureSummary {
// Extract just the service IDs as strings
services := make([]string, len(arch.Services))
for i, svc := range arch.Services {
services[i] = svc.ID
}

return types.ArchitectureSummary{
ID: arch.ID,
Name: arch.Name,
Description: arch.Description,
CertifiedBy: arch.CertifiedBy,
Services: services,
}
}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should we move these data transformers to types.go?

@yussufsh yussufsh marked this pull request as draft April 30, 2026 12:30
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants