Skill Plugin Development
Overview
In SERVICEME, a skill plugin refers to an optional capability for the Copilot. Beyond the system's built-in plugins, skill plugins can be expanded through development, enabling the Copilot with more functions.
System Built-in Skill Plugins
ID | Plugin | Type | Purpose |
---|---|---|---|
SearchKnowledgebase | Knowledge Base Search | API Plugin | Provides retrieval capabilities for private knowledge |
ImageGeneration | Image Generation | API Plugin | Generates images based on text descriptions |
Browsing | Web Browsing | API Plugin | Enables web browsing for real-time information search |
Charts | Charts | API Plugin | Generates corresponding charts (bar, line, pie) based on provided data |
DocumentReader | Document Reader | API Plugin | Provides summary information for single or selected documents |
QuestionContact | Question Contact | API Plugin | Returns the contact person for the relevant field based on the topic of the question |
Type Description
Type | Description |
---|---|
API Plugin | Skill plugins that function as backend APIs, where the Copilot fills API input parameters based on context and parses the API response |
API Skill Plugin
Supported Authentication Methods
Currently, only fixed Header authentication or no-authentication API calls are supported.
Type | Description |
---|---|
Fixed Header | Uses a fixed key in the request header for API authentication, similar to the OpenAI api_key format |
Plugin Development
To illustrate this process, let's take an API plugin that retrieves time zone information based on a time zone code as an example.
Step 1: First, provide an API that returns time zone information based on a time zone code.
API Example
- .NET (Web API)
- Java (Spring Boot)
- Python (Fast API)
- Javascript (Next.js)
using Microsoft.AspNetCore.Mvc;
using System;
namespace WorldTimeApi.Controllers
{
[ApiController]
[Route("api/[controller]")]
public class TimeController : ControllerBase
{
[HttpGet("current/zone")]
public IActionResult GetTimeByZone([FromQuery] string timeZone)
{
if (string.IsNullOrEmpty(timeZone))
{
return BadRequest("Missing required parameter: timeZone");
}
try
{
// Retrieve time zone information
var timeZoneInfo = TimeZoneInfo.FindSystemTimeZoneById(timeZone);
// Get current time in the specified time zone
var currentTime = TimeZoneInfo.ConvertTimeFromUtc(DateTime.UtcNow, timeZoneInfo);
// Return result
return Ok(new
{
TimeZone = timeZone,
CurrentTime = currentTime.ToString("yyyy-MM-ddTHH:mm:ss")
});
}
catch (TimeZoneNotFoundException)
{
return NotFound("Time zone not found");
}
catch (InvalidTimeZoneException)
{
return BadRequest("Invalid time zone");
}
catch (Exception ex)
{
return StatusCode(500, $"Internal server error: {ex.Message}");
}
}
}
}
package com.example.worldtime;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import java.time.Instant;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
@RestController
public class TimeController {
@GetMapping("/api/Time/current/zone")
public Object getTimeByZone(@RequestParam String timeZone) {
try {
ZoneId zoneId = ZoneId.of(timeZone);
ZonedDateTime currentTime = ZonedDateTime.ofInstant(Instant.now(), zoneId);
return new TimeResponse(timeZone, currentTime.format(DateTimeFormatter.ISO_LOCAL_DATE_TIME));
} catch (Exception e) {
return "Invalid time zone: " + e.getMessage();
}
}
static class TimeResponse {
public String timeZone;
public String currentTime;
public TimeResponse(String timeZone, String currentTime) {
this.timeZone = timeZone;
this.currentTime = currentTime;
}
}
}
from fastapi import FastAPI, HTTPException
from pydantic import BaseModel
from datetime import datetime
import pytz
app = FastAPI()
class TimeResponse(BaseModel):
timeZone: str
currentTime: str
@app.get("/api/Time/current/zone", response_model=TimeResponse)
async def get_time_by_zone(timeZone: str):
if not timeZone:
raise HTTPException(status_code=400, detail="Missing required parameter: timeZone")
try:
tz = pytz.timezone(timeZone)
current_time = datetime.now(tz)
return TimeResponse(
timeZone=timeZone,
currentTime=current_time.strftime('%Y-%m-%dT%H:%M:%S')
)
except pytz.UnknownTimeZoneError:
raise HTTPException(status_code=404, detail="Time zone not found")
except Exception as e:
raise HTTPException(status_code=500, detail=f"Internal server error: {str(e)}")
import moment from 'moment-timezone';
export default function handler(req, res) {
const { timeZone } = req.query;
if (!timeZone) {
return res.status(400).json({ error: 'Missing required parameter: timeZone' });
}
try {
const currentTime = moment().tz(timeZone).format('YYYY-MM-DDTHH:mm:ss');
res.status(200).json({
timeZone: timeZone,
currentTime: currentTime,
});
} catch (e) {
res.status(404).json({ error: 'Time zone not found' });
}
}
Step 2: Register this plugin in the system
Add a skill plugin and fill in the following information:
Field Descriptions
- Code: The unique identifier for the plugin within the system; try to use meaningful descriptors.
- Name: The display name of the plugin, which will be shown by Copilot during reasoning and execution. Ensure full language support.
- Description: The purpose of the plugin, which will be shown on the skill plugin addition page in Copilot.
- Request Header: Input any necessary Header parameters for calling the plugin, e.g., API_KEY.
- Important: OpenAPI / Swagger Schema (JSON): The main API description, which helps Copilot understand when and how to use this skill and fill in parameters.
OpenAPI Schema (JSON) Example
{
"Openapi": "3.0.0",
"Info": {
"Title": "World Time",
"Description": "Getting world time",
"Version": "v1.0.0"
},
"Servers": [
{
"Url": "https://www.timeapi.io"
}
],
"Paths": {
"/api/Time/current/zone": {
"Get": {
"OperationId": "zone",
"Description": "Get world time by timezone name",
"Deprecated": false,
"Parameters": [
{
"Name": "timeZone",
"In": "query",
"Required": true,
"Description": "Full IANA time zone names.",
"Schema": {
"Type": "string"
}
}
]
}
}
}
}
Notes
- Info/Title: This plugin title helps Copilot understand the plugin's purpose.
- Paths/[api path]/Get/OperationId: Use
\
%OperationId%`` in Copilot Prompts to specify API calls in certain scenarios, as demonstrated in step four below. - Paths/[api path]/Get/Description: Helps Copilot understand when to trigger this API.
- Paths/[api path]/Get/Parameters: Ensure consistency with the actual API, such as query parameters, and describe parameter names to increase fill success rates.
- Servers/Url: The base URL of the API; must be correct for successful calls.
- Optional: After configuring the plugin, use the DEBUG function for testing.
Step 3: Add the skill plugin to Copilot
In the Copilot settings interface, add the plugin through the [Skill Plugin] tab.
After saving, test by conversing with an expert.
Step 4: Optional - Add guidance in Copilot's Prompt to improve skill execution
Example
### Skill 3: Web Searching
- You can access web site by `Browsing` toolkit and look for HR information from the following sites: (site:*.linkedin.com; site:*.zhipin.com)
- Use results to fulfill the user's request and list reference links at the end of your response.
Note: In most cases, Copilot will determine the execution timing and parameter filling based on the information in the OpenAPI Schema.