Skip to content

Commit 601cc27

Browse files
authoredSep 16, 2024
Merge pull request #10 from copilot-extensions/sgoedecke/update-api-and-handle-wrong-model-names
v2 API, o1 models metadata, and support typos in model names
2 parents 96014d6 + 3032705 commit 601cc27

File tree

5 files changed

+68
-26
lines changed

5 files changed

+68
-26
lines changed
 

‎src/functions/describe-model.ts

+8-6
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,11 @@ export class describeModel extends Tool {
1010
properties: {
1111
model: {
1212
type: "string",
13-
description:
14-
'The model to describe. Looks like "registry/model-name". For example, `azureml/Phi-3-medium-128k-instruct` or `azure-openai/gpt-4o',
13+
description: [
14+
'The model to describe. Looks like "model-name". For example, `Phi-3-medium-128k-instruct` or `gpt-4o`.',
15+
'The list of models is available in the context window of the chat, in the `<-- LIST OF MODELS -->` section.',
16+
'If the model name is not found in the list of models, pick the closest matching model from the list.',
17+
].join("\n"),
1518
},
1619
},
1720
required: ["model"],
@@ -30,12 +33,11 @@ export class describeModel extends Tool {
3033
const systemMessage = [
3134
"The user is asking about the AI model with the following details:",
3235
`\tModel Name: ${model.name}`,
33-
`\tModel Version: ${model.model_version}`,
36+
`\tModel Version: ${model.version}`,
3437
`\tPublisher: ${model.publisher}`,
35-
`\tModel Family: ${model.model_family}`,
36-
`\tModel Registry: ${model.model_registry}`,
38+
`\tModel Registry: ${model.registryName}`,
3739
`\tLicense: ${model.license}`,
38-
`\tTask: ${model.task}`,
40+
`\tTask: ${model.inferenceTasks.join(", ")}`,
3941
`\tDescription: ${model.description}`,
4042
`\tSummary: ${model.summary}`,
4143
"\n",

‎src/functions/execute-model.ts

+1
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ Example Queries (IMPORTANT: Phrasing doesn't have to match):
3030
"The name of the model to execute. It is ONLY the name of the model, not the publisher or registry.",
3131
"For example: `gpt-4o`, or `cohere-command-r-plus`.",
3232
"The list of models is available in the context window of the chat, in the `<-- LIST OF MODELS -->` section.",
33+
"If the model name is not found in the list of models, pick the closest matching model from the list.",
3334
].join("\n"),
3435
},
3536
instruction: {

‎src/functions/list-models.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ export class listModels extends Tool {
2727
"That list of models is as follows:",
2828
JSON.stringify(
2929
models.map((model) => ({
30-
name: model.friendly_name,
30+
name: model.displayName,
3131
publisher: model.publisher,
3232
description: model.summary,
3333
}))

‎src/index.ts

+22-7
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ const server = createServer(async (request, response) => {
5555

5656
// List of functions that are available to be called
5757
const modelsAPI = new ModelsAPI(apiKey);
58+
5859
const functions = [listModels, describeModel, executeModel, recommendModel];
5960

6061
// Use the Copilot API to determine which function to execute
@@ -66,6 +67,7 @@ const server = createServer(async (request, response) => {
6667
// Prepend a system message that includes the list of models, so that
6768
// tool calls can better select the right model to use.
6869
const models = await modelsAPI.listModels();
70+
6971
const toolCallMessages = [
7072
{
7173
role: "system" as const,
@@ -75,13 +77,28 @@ const server = createServer(async (request, response) => {
7577
"Here is a list of some of the models available to the user:",
7678
"<-- LIST OF MODELS -->",
7779
JSON.stringify(
78-
models.map((model) => ({
79-
friendly_name: model.friendly_name,
80+
[...models.map((model) => ({
81+
friendly_name: model.displayName,
8082
name: model.name,
8183
publisher: model.publisher,
82-
registry: model.model_registry,
84+
registry: model.registryName,
8385
description: model.summary,
84-
}))
86+
})),
87+
{
88+
friendly_name: "OpenAI o1-mini",
89+
name: "o1-mini",
90+
publisher: "openai",
91+
model_registry: "azure-openai",
92+
description: "Smaller, faster, and 80% cheaper than o1-preview, performs well at code generation and small context operations."
93+
},
94+
{
95+
friendly_name: "OpenAI o1-preview",
96+
name: "o1-preview",
97+
publisher: "openai",
98+
model_registry: "azure-openai",
99+
description: "Focused on advanced reasoning and solving complex problems, including math and science tasks. Ideal for applications that require deep contextual understanding and agentic workflows."
100+
},
101+
]
85102
),
86103
"<-- END OF LIST OF MODELS -->",
87104
].join("\n"),
@@ -148,13 +165,11 @@ const server = createServer(async (request, response) => {
148165
console.timeEnd("function-exec");
149166

150167
try {
168+
// We should keep all optional parameters out of this call, so it can work for any model.
151169
const stream = await modelsAPI.inference.chat.completions.create({
152170
model: functionCallRes.model,
153171
messages: functionCallRes.messages,
154172
stream: true,
155-
stream_options: {
156-
include_usage: false,
157-
},
158173
});
159174

160175
console.time("streaming");

‎src/models-api.ts

+36-12
Original file line numberDiff line numberDiff line change
@@ -2,16 +2,14 @@ import OpenAI from "openai";
22

33
// Model is the structure of a model in the model catalog.
44
export interface Model {
5-
id: string;
65
name: string;
7-
friendly_name: string;
8-
model_version: number;
6+
displayName: string;
7+
version: string;
98
publisher: string;
10-
model_family: string;
11-
model_registry: string;
9+
registryName: string;
1210
license: string;
13-
task: string;
14-
description: string;
11+
inferenceTasks: string[];
12+
description?: string;
1513
summary: string;
1614
}
1715

@@ -44,19 +42,23 @@ export class ModelsAPI {
4442
}
4543

4644
async getModel(modelName: string): Promise<Model> {
45+
const modelFromIndex = await this.getModelFromIndex(modelName);
46+
4747
const modelRes = await fetch(
48-
"https://modelcatalog.azure-api.net/v1/model/" + modelName
48+
`https://eastus.api.azureml.ms/asset-gallery/v1.0/${modelFromIndex.registryName}/models/${modelFromIndex.name}/version/${modelFromIndex.version}`,
4949
);
5050
if (!modelRes.ok) {
51-
throw new Error(`Failed to fetch ${modelName} from the model catalog.`);
51+
throw new Error(`Failed to fetch ${modelName} details from the model catalog.`);
5252
}
5353
const model = (await modelRes.json()) as Model;
5454
return model;
5555
}
5656

5757
async getModelSchema(modelName: string): Promise<ModelSchema> {
58+
const modelFromIndex = await this.getModelFromIndex(modelName);
59+
5860
const modelSchemaRes = await fetch(
59-
`https://modelcatalogcachev2-ebendjczf0c5dzca.b02.azurefd.net/widgets/en/Serverless/${modelName.toLowerCase()}.json`
61+
`https://modelcatalogcachev2-ebendjczf0c5dzca.b02.azurefd.net/widgets/en/Serverless/${modelFromIndex.registryName.toLowerCase()}/${modelFromIndex.name.toLowerCase()}.json`
6062
);
6163
if (!modelSchemaRes.ok) {
6264
throw new Error(
@@ -73,14 +75,36 @@ export class ModelsAPI {
7375
}
7476

7577
const modelsRes = await fetch(
76-
"https://modelcatalog.azure-api.net/v1/models"
78+
"https://eastus.api.azureml.ms/asset-gallery/v1.0/models",
79+
{
80+
method: "POST",
81+
headers: {
82+
"Content-Type": "application/json",
83+
},
84+
body: JSON.stringify({
85+
filters: [
86+
{ field: "freePlayground", values: ["true"], operator: "eq" },
87+
{ field: "labels", values: ["latest"], operator: "eq" },
88+
],
89+
order: [{ field: "displayName", direction: "Asc" }],
90+
}),
91+
}
7792
);
7893
if (!modelsRes.ok) {
7994
throw new Error("Failed to fetch models from the model catalog");
8095
}
8196

82-
const models = (await modelsRes.json()) as Model[];
97+
const models = (await modelsRes.json()).summaries as Model[];
8398
this._models = models;
8499
return models;
85100
}
101+
102+
async getModelFromIndex(modelName: string): Promise<Model> {
103+
this._models = this._models || (await this.listModels());
104+
const modelFromIndex = this._models.find((model) => model.name === modelName);
105+
if (!modelFromIndex) {
106+
throw new Error(`Failed to fetch ${modelName} from the model catalog.`);
107+
}
108+
return modelFromIndex;
109+
}
86110
}

0 commit comments

Comments
 (0)
Failed to load comments.