@azure-rest/ai-inference 1.0.0-beta.5 → 1.0.0-beta.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +3 -3
- package/README.md +253 -249
- package/dist/browser/clientDefinitions.d.ts +10 -3
- package/dist/browser/clientDefinitions.d.ts.map +1 -1
- package/dist/browser/clientDefinitions.js.map +1 -1
- package/dist/browser/constants.d.ts +7 -0
- package/dist/browser/constants.d.ts.map +1 -1
- package/dist/browser/constants.js +7 -0
- package/dist/browser/constants.js.map +1 -1
- package/dist/browser/index.d.ts +11 -3
- package/dist/browser/index.d.ts.map +1 -1
- package/dist/browser/index.js +10 -3
- package/dist/browser/index.js.map +1 -1
- package/dist/browser/isUnexpected.d.ts +8 -1
- package/dist/browser/isUnexpected.d.ts.map +1 -1
- package/dist/browser/isUnexpected.js +1 -6
- package/dist/browser/isUnexpected.js.map +1 -1
- package/dist/browser/logger.d.ts.map +1 -1
- package/dist/browser/logger.js +7 -0
- package/dist/browser/logger.js.map +1 -1
- package/dist/browser/modelClient.d.ts +7 -0
- package/dist/browser/modelClient.d.ts.map +1 -1
- package/dist/browser/modelClient.js +1 -1
- package/dist/browser/modelClient.js.map +1 -1
- package/dist/browser/models.d.ts +57 -8
- package/dist/browser/models.d.ts.map +1 -1
- package/dist/browser/models.js.map +1 -1
- package/dist/browser/outputModels.d.ts +23 -16
- package/dist/browser/outputModels.d.ts.map +1 -1
- package/dist/browser/outputModels.js.map +1 -1
- package/dist/browser/parameters.d.ts +13 -6
- package/dist/browser/parameters.d.ts.map +1 -1
- package/dist/browser/parameters.js.map +1 -1
- package/dist/browser/responses.d.ts +9 -2
- package/dist/browser/responses.d.ts.map +1 -1
- package/dist/browser/responses.js.map +1 -1
- package/dist/browser/tracingHelper.d.ts +8 -1
- package/dist/browser/tracingHelper.d.ts.map +1 -1
- package/dist/browser/tracingHelper.js +26 -26
- package/dist/browser/tracingHelper.js.map +1 -1
- package/dist/browser/tracingPolicy.d.ts +7 -0
- package/dist/browser/tracingPolicy.d.ts.map +1 -1
- package/dist/browser/tracingPolicy.js +2 -2
- package/dist/browser/tracingPolicy.js.map +1 -1
- package/dist/commonjs/clientDefinitions.d.ts +10 -3
- package/dist/commonjs/clientDefinitions.d.ts.map +1 -1
- package/dist/commonjs/clientDefinitions.js.map +1 -1
- package/dist/commonjs/constants.d.ts +7 -0
- package/dist/commonjs/constants.d.ts.map +1 -1
- package/dist/commonjs/constants.js +9 -2
- package/dist/commonjs/constants.js.map +1 -1
- package/dist/commonjs/index.d.ts +11 -3
- package/dist/commonjs/index.d.ts.map +1 -1
- package/dist/commonjs/index.js +10 -3
- package/dist/commonjs/index.js.map +1 -1
- package/dist/commonjs/isUnexpected.d.ts +8 -1
- package/dist/commonjs/isUnexpected.d.ts.map +1 -1
- package/dist/commonjs/isUnexpected.js +1 -6
- package/dist/commonjs/isUnexpected.js.map +1 -1
- package/dist/commonjs/logger.d.ts.map +1 -1
- package/dist/commonjs/logger.js +7 -0
- package/dist/commonjs/logger.js.map +1 -1
- package/dist/commonjs/modelClient.d.ts +7 -0
- package/dist/commonjs/modelClient.d.ts.map +1 -1
- package/dist/commonjs/modelClient.js +1 -1
- package/dist/commonjs/modelClient.js.map +1 -1
- package/dist/commonjs/models.d.ts +57 -8
- package/dist/commonjs/models.d.ts.map +1 -1
- package/dist/commonjs/models.js.map +1 -1
- package/dist/commonjs/outputModels.d.ts +23 -16
- package/dist/commonjs/outputModels.d.ts.map +1 -1
- package/dist/commonjs/outputModels.js.map +1 -1
- package/dist/commonjs/parameters.d.ts +13 -6
- package/dist/commonjs/parameters.d.ts.map +1 -1
- package/dist/commonjs/parameters.js.map +1 -1
- package/dist/commonjs/responses.d.ts +9 -2
- package/dist/commonjs/responses.d.ts.map +1 -1
- package/dist/commonjs/responses.js.map +1 -1
- package/dist/commonjs/tracingHelper.d.ts +8 -1
- package/dist/commonjs/tracingHelper.d.ts.map +1 -1
- package/dist/commonjs/tracingHelper.js +26 -26
- package/dist/commonjs/tracingHelper.js.map +1 -1
- package/dist/commonjs/tracingPolicy.d.ts +7 -0
- package/dist/commonjs/tracingPolicy.d.ts.map +1 -1
- package/dist/commonjs/tracingPolicy.js +2 -2
- package/dist/commonjs/tracingPolicy.js.map +1 -1
- package/dist/commonjs/tsdoc-metadata.json +1 -1
- package/dist/esm/clientDefinitions.d.ts +10 -3
- package/dist/esm/clientDefinitions.d.ts.map +1 -1
- package/dist/esm/clientDefinitions.js.map +1 -1
- package/dist/esm/constants.d.ts +7 -0
- package/dist/esm/constants.d.ts.map +1 -1
- package/dist/esm/constants.js +7 -0
- package/dist/esm/constants.js.map +1 -1
- package/dist/esm/index.d.ts +11 -3
- package/dist/esm/index.d.ts.map +1 -1
- package/dist/esm/index.js +10 -3
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/isUnexpected.d.ts +8 -1
- package/dist/esm/isUnexpected.d.ts.map +1 -1
- package/dist/esm/isUnexpected.js +1 -6
- package/dist/esm/isUnexpected.js.map +1 -1
- package/dist/esm/logger.d.ts.map +1 -1
- package/dist/esm/logger.js +7 -0
- package/dist/esm/logger.js.map +1 -1
- package/dist/esm/modelClient.d.ts +7 -0
- package/dist/esm/modelClient.d.ts.map +1 -1
- package/dist/esm/modelClient.js +1 -1
- package/dist/esm/modelClient.js.map +1 -1
- package/dist/esm/models.d.ts +57 -8
- package/dist/esm/models.d.ts.map +1 -1
- package/dist/esm/models.js.map +1 -1
- package/dist/esm/outputModels.d.ts +23 -16
- package/dist/esm/outputModels.d.ts.map +1 -1
- package/dist/esm/outputModels.js.map +1 -1
- package/dist/esm/parameters.d.ts +13 -6
- package/dist/esm/parameters.d.ts.map +1 -1
- package/dist/esm/parameters.js.map +1 -1
- package/dist/esm/responses.d.ts +9 -2
- package/dist/esm/responses.d.ts.map +1 -1
- package/dist/esm/responses.js.map +1 -1
- package/dist/esm/tracingHelper.d.ts +8 -1
- package/dist/esm/tracingHelper.d.ts.map +1 -1
- package/dist/esm/tracingHelper.js +26 -26
- package/dist/esm/tracingHelper.js.map +1 -1
- package/dist/esm/tracingPolicy.d.ts +7 -0
- package/dist/esm/tracingPolicy.d.ts.map +1 -1
- package/dist/esm/tracingPolicy.js +2 -2
- package/dist/esm/tracingPolicy.js.map +1 -1
- package/dist/react-native/clientDefinitions.d.ts +10 -3
- package/dist/react-native/clientDefinitions.d.ts.map +1 -1
- package/dist/react-native/clientDefinitions.js.map +1 -1
- package/dist/react-native/constants.d.ts +7 -0
- package/dist/react-native/constants.d.ts.map +1 -1
- package/dist/react-native/constants.js +7 -0
- package/dist/react-native/constants.js.map +1 -1
- package/dist/react-native/index.d.ts +11 -3
- package/dist/react-native/index.d.ts.map +1 -1
- package/dist/react-native/index.js +10 -3
- package/dist/react-native/index.js.map +1 -1
- package/dist/react-native/isUnexpected.d.ts +8 -1
- package/dist/react-native/isUnexpected.d.ts.map +1 -1
- package/dist/react-native/isUnexpected.js +1 -6
- package/dist/react-native/isUnexpected.js.map +1 -1
- package/dist/react-native/logger.d.ts.map +1 -1
- package/dist/react-native/logger.js +7 -0
- package/dist/react-native/logger.js.map +1 -1
- package/dist/react-native/modelClient.d.ts +7 -0
- package/dist/react-native/modelClient.d.ts.map +1 -1
- package/dist/react-native/modelClient.js +1 -1
- package/dist/react-native/modelClient.js.map +1 -1
- package/dist/react-native/models.d.ts +57 -8
- package/dist/react-native/models.d.ts.map +1 -1
- package/dist/react-native/models.js.map +1 -1
- package/dist/react-native/outputModels.d.ts +23 -16
- package/dist/react-native/outputModels.d.ts.map +1 -1
- package/dist/react-native/outputModels.js.map +1 -1
- package/dist/react-native/parameters.d.ts +13 -6
- package/dist/react-native/parameters.d.ts.map +1 -1
- package/dist/react-native/parameters.js.map +1 -1
- package/dist/react-native/responses.d.ts +9 -2
- package/dist/react-native/responses.d.ts.map +1 -1
- package/dist/react-native/responses.js.map +1 -1
- package/dist/react-native/tracingHelper.d.ts +8 -1
- package/dist/react-native/tracingHelper.d.ts.map +1 -1
- package/dist/react-native/tracingHelper.js +26 -26
- package/dist/react-native/tracingHelper.js.map +1 -1
- package/dist/react-native/tracingPolicy.d.ts +7 -0
- package/dist/react-native/tracingPolicy.d.ts.map +1 -1
- package/dist/react-native/tracingPolicy.js +2 -2
- package/dist/react-native/tracingPolicy.js.map +1 -1
- package/package.json +28 -25
package/README.md
CHANGED
|
@@ -13,10 +13,11 @@ Key links:
|
|
|
13
13
|
|
|
14
14
|
## Getting started
|
|
15
15
|
|
|
16
|
-
```
|
|
16
|
+
```ts snippet:ReadmeSample_Node
|
|
17
17
|
import ModelClient, { isUnexpected } from "@azure-rest/ai-inference";
|
|
18
18
|
import { AzureKeyCredential } from "@azure/core-auth";
|
|
19
|
-
|
|
19
|
+
|
|
20
|
+
const client = ModelClient(
|
|
20
21
|
"https://<Azure Model endpoint>",
|
|
21
22
|
new AzureKeyCredential("<Azure API key>"),
|
|
22
23
|
);
|
|
@@ -43,13 +44,13 @@ console.log(response.body.choices[0].message.content);
|
|
|
43
44
|
|
|
44
45
|
### Install the `@azure-rest/ai-inference` package
|
|
45
46
|
|
|
46
|
-
Install the Azure
|
|
47
|
+
Install the Azure Inference REST client library for JavaScript with `npm`:
|
|
47
48
|
|
|
48
49
|
```bash
|
|
49
50
|
npm install @azure-rest/ai-inference
|
|
50
51
|
```
|
|
51
52
|
|
|
52
|
-
### Create and authenticate
|
|
53
|
+
### Create and authenticate the Inference client
|
|
53
54
|
|
|
54
55
|
#### Using an API Key from Azure
|
|
55
56
|
|
|
@@ -65,11 +66,11 @@ Use the [Azure Portal][azure_portal] to browse to your Model deployment and retr
|
|
|
65
66
|
|
|
66
67
|
Once you have an API key and endpoint, you can use the `AzureKeyCredential` class to authenticate the client as follows:
|
|
67
68
|
|
|
68
|
-
```
|
|
69
|
+
```ts snippet:ReadmeSample_KeyCredential
|
|
69
70
|
import ModelClient from "@azure-rest/ai-inference";
|
|
70
71
|
import { AzureKeyCredential } from "@azure/core-auth";
|
|
71
72
|
|
|
72
|
-
const client =
|
|
73
|
+
const client = ModelClient("<endpoint>", new AzureKeyCredential("<API key>"));
|
|
73
74
|
```
|
|
74
75
|
|
|
75
76
|
#### Using an Azure Active Directory Credential
|
|
@@ -83,43 +84,37 @@ npm install @azure/identity
|
|
|
83
84
|
|
|
84
85
|
Set the values of the client ID, tenant ID, and client secret of the AAD application as environment variables: `AZURE_CLIENT_ID`, `AZURE_TENANT_ID`, `AZURE_CLIENT_SECRET`.
|
|
85
86
|
|
|
86
|
-
```
|
|
87
|
+
```ts snippet:ReadmeSample_TokenCredential
|
|
87
88
|
import ModelClient from "@azure-rest/ai-inference";
|
|
88
89
|
import { DefaultAzureCredential } from "@azure/identity";
|
|
89
90
|
|
|
90
|
-
const client =
|
|
91
|
+
const client = ModelClient("<endpoint>", new DefaultAzureCredential());
|
|
91
92
|
```
|
|
92
93
|
|
|
93
94
|
## Key concepts
|
|
94
95
|
|
|
95
96
|
The main concept to understand is [Completions][azure_openai_completions_docs]. Briefly explained, completions provides its functionality in the form of a text prompt, which by using a specific [model](https://learn.microsoft.com/azure/cognitive-services/openai/concepts/models), will then attempt to match the context and patterns, providing an output text. The following code snippet provides a rough overview:
|
|
96
97
|
|
|
97
|
-
```
|
|
98
|
+
```ts snippet:ReadmeSample_Completions
|
|
98
99
|
import ModelClient, { isUnexpected } from "@azure-rest/ai-inference";
|
|
99
100
|
import { AzureKeyCredential } from "@azure/core-auth";
|
|
100
101
|
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
);
|
|
106
|
-
|
|
107
|
-
const response = await client.path("/chat/completions").post({
|
|
108
|
-
body: {
|
|
109
|
-
messages: [{ role: "user", content: "Hello, world!" }],
|
|
110
|
-
},
|
|
111
|
-
});
|
|
102
|
+
const client = ModelClient(
|
|
103
|
+
"https://your-model-endpoint/",
|
|
104
|
+
new AzureKeyCredential("your-model-api-key"),
|
|
105
|
+
);
|
|
112
106
|
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
107
|
+
const response = await client.path("/chat/completions").post({
|
|
108
|
+
body: {
|
|
109
|
+
messages: [{ role: "user", content: "Hello, world!" }],
|
|
110
|
+
},
|
|
111
|
+
});
|
|
116
112
|
|
|
117
|
-
|
|
113
|
+
if (isUnexpected(response)) {
|
|
114
|
+
throw response.body.error;
|
|
118
115
|
}
|
|
119
116
|
|
|
120
|
-
|
|
121
|
-
console.error("The sample encountered an error:", err);
|
|
122
|
-
});
|
|
117
|
+
console.log(response.body.choices[0].message.content);
|
|
123
118
|
```
|
|
124
119
|
|
|
125
120
|
## Examples
|
|
@@ -134,129 +129,117 @@ npm install @azure/core-sse
|
|
|
134
129
|
|
|
135
130
|
This example authenticates using a DefaultAzureCredential, then generates chat responses to input chat question and messages.
|
|
136
131
|
|
|
137
|
-
```
|
|
132
|
+
```ts snippet:ReadmeSample_ChatbotResponse
|
|
138
133
|
import ModelClient from "@azure-rest/ai-inference";
|
|
139
134
|
import { DefaultAzureCredential } from "@azure/identity";
|
|
140
135
|
import { createSseStream } from "@azure/core-sse";
|
|
136
|
+
import { IncomingMessage } from "node:http";
|
|
141
137
|
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
const client = new ModelClient(endpoint, new DefaultAzureCredential());
|
|
145
|
-
|
|
146
|
-
const messages = [
|
|
147
|
-
// NOTE: "system" role is not supported on all Azure Models
|
|
148
|
-
{ role: "system", content: "You are a helpful assistant. You will talk like a pirate." },
|
|
149
|
-
{ role: "user", content: "Can you help me?" },
|
|
150
|
-
{ role: "assistant", content: "Arrrr! Of course, me hearty! What can I do for ye?" },
|
|
151
|
-
{ role: "user", content: "What's the best way to train a parrot?" },
|
|
152
|
-
];
|
|
153
|
-
|
|
154
|
-
console.log(`Messages: ${messages.map((m) => m.content).join("\n")}`);
|
|
155
|
-
|
|
156
|
-
const response = await client
|
|
157
|
-
.path("/chat/completions")
|
|
158
|
-
.post({
|
|
159
|
-
body: {
|
|
160
|
-
messages,
|
|
161
|
-
stream: true,
|
|
162
|
-
max_tokens: 128,
|
|
163
|
-
},
|
|
164
|
-
})
|
|
165
|
-
.asNodeStream();
|
|
138
|
+
const endpoint = "https://myaccount.openai.azure.com/";
|
|
139
|
+
const client = ModelClient(endpoint, new DefaultAzureCredential());
|
|
166
140
|
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
}
|
|
141
|
+
const messages = [
|
|
142
|
+
// NOTE: "system" role is not supported on all Azure Models
|
|
143
|
+
{ role: "system", content: "You are a helpful assistant. You will talk like a pirate." },
|
|
144
|
+
{ role: "user", content: "Can you help me?" },
|
|
145
|
+
{ role: "assistant", content: "Arrrr! Of course, me hearty! What can I do for ye?" },
|
|
146
|
+
{ role: "user", content: "What's the best way to train a parrot?" },
|
|
147
|
+
];
|
|
171
148
|
|
|
172
|
-
|
|
173
|
-
throw new Error(`Failed to get chat completions: ${response.body.error}`);
|
|
174
|
-
}
|
|
149
|
+
console.log(`Messages: ${messages.map((m) => m.content).join("\n")}`);
|
|
175
150
|
|
|
176
|
-
|
|
151
|
+
const response = await client
|
|
152
|
+
.path("/chat/completions")
|
|
153
|
+
.post({
|
|
154
|
+
body: {
|
|
155
|
+
messages,
|
|
156
|
+
stream: true,
|
|
157
|
+
max_tokens: 128,
|
|
158
|
+
},
|
|
159
|
+
})
|
|
160
|
+
.asNodeStream();
|
|
177
161
|
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
}
|
|
182
|
-
for (const choice of JSON.parse(event.data).choices) {
|
|
183
|
-
console.log(choice.delta?.content ?? "");
|
|
184
|
-
}
|
|
185
|
-
}
|
|
162
|
+
const stream = response.body;
|
|
163
|
+
if (!stream) {
|
|
164
|
+
throw new Error("The response stream is undefined");
|
|
186
165
|
}
|
|
187
166
|
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
}
|
|
167
|
+
if (response.status !== "200") {
|
|
168
|
+
throw new Error("Failed to get chat completions");
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
const sses = createSseStream(stream as IncomingMessage);
|
|
172
|
+
|
|
173
|
+
for await (const event of sses) {
|
|
174
|
+
if (event.data === "[DONE]") {
|
|
175
|
+
return;
|
|
176
|
+
}
|
|
177
|
+
for (const choice of JSON.parse(event.data).choices) {
|
|
178
|
+
console.log(choice.delta?.content ?? "");
|
|
179
|
+
}
|
|
180
|
+
}
|
|
191
181
|
```
|
|
192
182
|
|
|
193
183
|
### Generate Multiple Completions With Subscription Key
|
|
194
184
|
|
|
195
185
|
This example generates text responses to input prompts using an Azure subscription key
|
|
196
186
|
|
|
197
|
-
```
|
|
198
|
-
import ModelClient from "@azure-rest/ai-inference";
|
|
187
|
+
```ts snippet:ReadmeSample_MultipleCompletions
|
|
188
|
+
import ModelClient, { isUnexpected } from "@azure-rest/ai-inference";
|
|
199
189
|
import { AzureKeyCredential } from "@azure/core-auth";
|
|
200
190
|
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
const client = new ModelClient(endpoint, new AzureKeyCredential(key));
|
|
206
|
-
|
|
207
|
-
const messages = [
|
|
208
|
-
{ role: "user", content: "How are you today?" },
|
|
209
|
-
{ role: "user", content: "What is inference in the context of AI?" },
|
|
210
|
-
{ role: "user", content: "Why do children love dinosaurs?" },
|
|
211
|
-
{ role: "user", content: "Generate a proof of Euler's identity" },
|
|
212
|
-
{
|
|
213
|
-
role: "user",
|
|
214
|
-
content:
|
|
215
|
-
"Describe in single words only the good things that come into your mind about your mother.",
|
|
216
|
-
},
|
|
217
|
-
];
|
|
218
|
-
|
|
219
|
-
let promptIndex = 0;
|
|
220
|
-
const response = await client.path("/chat/completions").post({
|
|
221
|
-
body: {
|
|
222
|
-
messages,
|
|
223
|
-
},
|
|
224
|
-
});
|
|
191
|
+
// Replace with your Model API key
|
|
192
|
+
const key = "YOUR_MODEL_API_KEY";
|
|
193
|
+
const endpoint = "https://your-model-endpoint/";
|
|
194
|
+
const client = ModelClient(endpoint, new AzureKeyCredential(key));
|
|
225
195
|
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
}
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
196
|
+
const messages = [
|
|
197
|
+
{ role: "user", content: "How are you today?" },
|
|
198
|
+
{ role: "user", content: "What is inference in the context of AI?" },
|
|
199
|
+
{ role: "user", content: "Why do children love dinosaurs?" },
|
|
200
|
+
{ role: "user", content: "Generate a proof of Euler's identity" },
|
|
201
|
+
{
|
|
202
|
+
role: "user",
|
|
203
|
+
content:
|
|
204
|
+
"Describe in single words only the good things that come into your mind about your mother.",
|
|
205
|
+
},
|
|
206
|
+
];
|
|
235
207
|
|
|
236
|
-
|
|
237
|
-
|
|
208
|
+
let promptIndex = 0;
|
|
209
|
+
const response = await client.path("/chat/completions").post({
|
|
210
|
+
body: {
|
|
211
|
+
messages,
|
|
212
|
+
},
|
|
238
213
|
});
|
|
214
|
+
|
|
215
|
+
if (isUnexpected(response)) {
|
|
216
|
+
throw response.body.error;
|
|
217
|
+
}
|
|
218
|
+
for (const choice of response.body.choices) {
|
|
219
|
+
const completion = choice.message.content;
|
|
220
|
+
console.log(`Input: ${messages[promptIndex++].content}`);
|
|
221
|
+
console.log(`Chatbot: ${completion}`);
|
|
222
|
+
}
|
|
239
223
|
```
|
|
240
224
|
|
|
241
225
|
### Summarize Text with Completion
|
|
242
226
|
|
|
243
227
|
This example generates a summarization of the given input prompt.
|
|
244
228
|
|
|
245
|
-
```
|
|
246
|
-
import ModelClient from "@azure-rest/ai-inference";
|
|
229
|
+
```ts snippet:ReadmeSample_SummarizeText
|
|
230
|
+
import ModelClient, { isUnexpected } from "@azure-rest/ai-inference";
|
|
247
231
|
import { DefaultAzureCredential } from "@azure/identity";
|
|
248
232
|
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
const client = new ModelClient(endpoint, new DefaultAzureCredential());
|
|
233
|
+
const endpoint = "https://myaccount.openai.azure.com/";
|
|
234
|
+
const client = ModelClient(endpoint, new DefaultAzureCredential());
|
|
252
235
|
|
|
253
|
-
|
|
236
|
+
const textToSummarize = `
|
|
254
237
|
Two independent experiments reported their results this morning at CERN, Europe's high-energy physics laboratory near Geneva in Switzerland. Both show convincing evidence of a new boson particle weighing around 125 gigaelectronvolts, which so far fits predictions of the Higgs previously made by theoretical physicists.
|
|
255
238
|
|
|
256
239
|
""As a layman I would say: 'I think we have it'. Would you agree?"" Rolf-Dieter Heuer, CERN's director-general, asked the packed auditorium. The physicists assembled there burst into applause.
|
|
257
240
|
:`;
|
|
258
241
|
|
|
259
|
-
|
|
242
|
+
const summarizationPrompt = `
|
|
260
243
|
Summarize the following text.
|
|
261
244
|
|
|
262
245
|
Text:
|
|
@@ -267,33 +250,34 @@ async function main() {
|
|
|
267
250
|
Summary:
|
|
268
251
|
`;
|
|
269
252
|
|
|
270
|
-
|
|
253
|
+
console.log(`Input: ${summarizationPrompt}`);
|
|
271
254
|
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
255
|
+
const response = await client.path("/chat/completions").post({
|
|
256
|
+
body: {
|
|
257
|
+
messages: [{ role: "user", content: summarizationPrompt }],
|
|
258
|
+
max_tokens: 64,
|
|
259
|
+
},
|
|
260
|
+
});
|
|
278
261
|
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
}
|
|
282
|
-
const completion = response.body.choices[0].message.content;
|
|
283
|
-
console.log(`Summarization: ${completion}`);
|
|
262
|
+
if (isUnexpected(response)) {
|
|
263
|
+
throw response.body.error;
|
|
284
264
|
}
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
console.error("The sample encountered an error:", err);
|
|
288
|
-
});
|
|
265
|
+
const completion = response.body.choices[0].message.content;
|
|
266
|
+
console.log(`Summarization: ${completion}`);
|
|
289
267
|
```
|
|
290
268
|
|
|
291
269
|
### Use chat tools
|
|
292
270
|
|
|
293
271
|
**Tools** extend chat completions by allowing an assistant to invoke defined functions and other capabilities in the
|
|
294
|
-
process of fulfilling a chat completions request. To use chat tools, start by defining a function tool:
|
|
272
|
+
process of fulfilling a chat completions request. To use chat tools, start by defining a function tool named `getCurrentWeather`. With the tool defined, include that new definition in the options for a chat completions request:
|
|
273
|
+
|
|
274
|
+
```ts snippet:ReadmeSample_ChatTools
|
|
275
|
+
import ModelClient from "@azure-rest/ai-inference";
|
|
276
|
+
import { DefaultAzureCredential } from "@azure/identity";
|
|
277
|
+
|
|
278
|
+
const endpoint = "https://myaccount.openai.azure.com/";
|
|
279
|
+
const client = ModelClient(endpoint, new DefaultAzureCredential());
|
|
295
280
|
|
|
296
|
-
```js
|
|
297
281
|
const getCurrentWeather = {
|
|
298
282
|
name: "get_current_weather",
|
|
299
283
|
description: "Get the current weather in a given location",
|
|
@@ -312,22 +296,17 @@ const getCurrentWeather = {
|
|
|
312
296
|
required: ["location"],
|
|
313
297
|
},
|
|
314
298
|
};
|
|
315
|
-
```
|
|
316
|
-
|
|
317
|
-
With the tool defined, include that new definition in the options for a chat completions request:
|
|
318
299
|
|
|
319
|
-
```js
|
|
320
300
|
const messages = [{ role: "user", content: "What is the weather like in Boston?" }];
|
|
321
|
-
const tools = [
|
|
322
|
-
{
|
|
323
|
-
type: "function",
|
|
324
|
-
function: getCurrentWeather,
|
|
325
|
-
},
|
|
326
|
-
];
|
|
327
301
|
const result = await client.path("/chat/completions").post({
|
|
328
302
|
body: {
|
|
329
303
|
messages,
|
|
330
|
-
tools
|
|
304
|
+
tools: [
|
|
305
|
+
{
|
|
306
|
+
type: "function",
|
|
307
|
+
function: getCurrentWeather,
|
|
308
|
+
},
|
|
309
|
+
],
|
|
331
310
|
},
|
|
332
311
|
});
|
|
333
312
|
```
|
|
@@ -336,7 +315,7 @@ When the assistant decides that one or more tools should be used, the response m
|
|
|
336
315
|
calls" that must all be resolved via "tool messages" on the subsequent request. This resolution of tool calls into
|
|
337
316
|
new request messages can be thought of as a sort of "callback" for chat completions.
|
|
338
317
|
|
|
339
|
-
```
|
|
318
|
+
```ts snippet:ReadmeSample_ChatToolsResponse
|
|
340
319
|
// Purely for convenience and clarity, this function handles tool call responses.
|
|
341
320
|
function applyToolCall({ function: call, id }) {
|
|
342
321
|
if (call.name === "get_current_weather") {
|
|
@@ -356,23 +335,39 @@ To provide tool call resolutions to the assistant to allow the request to contin
|
|
|
356
335
|
context -- including the original system and user messages, the response from the assistant that included the tool
|
|
357
336
|
calls, and the tool messages that resolved each of those tools -- when making a subsequent request.
|
|
358
337
|
|
|
359
|
-
```
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
338
|
+
```ts snippet:ReadmeSample_ChatToolsResolution
|
|
339
|
+
import ModelClient from "@azure-rest/ai-inference";
|
|
340
|
+
import { DefaultAzureCredential } from "@azure/identity";
|
|
341
|
+
|
|
342
|
+
const endpoint = "https://myaccount.openai.azure.com/";
|
|
343
|
+
const client = ModelClient(endpoint, new DefaultAzureCredential());
|
|
344
|
+
|
|
345
|
+
// From previous snippets
|
|
346
|
+
const messages = [{ role: "user", content: "What is the weather like in Boston?" }];
|
|
347
|
+
|
|
348
|
+
function applyToolCall({ function: call, id }) {
|
|
349
|
+
// from previous snippet
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
// Handle result from previous snippet
|
|
353
|
+
async function handleResponse(result) {
|
|
354
|
+
const choice = result.body.choices[0];
|
|
355
|
+
const responseMessage = choice.message;
|
|
356
|
+
if (responseMessage?.role === "assistant") {
|
|
357
|
+
const requestedToolCalls = responseMessage?.toolCalls;
|
|
358
|
+
if (requestedToolCalls?.length) {
|
|
359
|
+
const toolCallResolutionMessages = [
|
|
360
|
+
...messages,
|
|
361
|
+
responseMessage,
|
|
362
|
+
...requestedToolCalls.map(applyToolCall),
|
|
363
|
+
];
|
|
364
|
+
const toolCallResolutionResult = await client.path("/chat/completions").post({
|
|
365
|
+
body: {
|
|
366
|
+
messages: toolCallResolutionMessages,
|
|
367
|
+
},
|
|
368
|
+
});
|
|
369
|
+
// continue handling the response as normal
|
|
370
|
+
}
|
|
376
371
|
}
|
|
377
372
|
}
|
|
378
373
|
```
|
|
@@ -381,64 +376,71 @@ if (responseMessage?.role === "assistant") {
|
|
|
381
376
|
|
|
382
377
|
Some Azure models allow you to use images as input components into chat completions.
|
|
383
378
|
|
|
384
|
-
To do this, provide distinct content items on the user message(s) for the chat completions request
|
|
379
|
+
To do this, provide distinct content items on the user message(s) for the chat completions request. Chat Completions will then proceed as usual, though the model may report the more informative `finish_details` in lieu
|
|
380
|
+
of `finish_reason`.
|
|
385
381
|
|
|
386
|
-
```
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
role: "user", content: [{
|
|
390
|
-
type: "image_url",
|
|
391
|
-
image_url: {
|
|
392
|
-
url,
|
|
393
|
-
detail: "auto"
|
|
394
|
-
}
|
|
395
|
-
}]},
|
|
396
|
-
{role: "user", content: "describe the image"}];
|
|
397
|
-
```
|
|
382
|
+
```ts snippet:ReadmeSample_ChatWithImages
|
|
383
|
+
import ModelClient, { isUnexpected } from "@azure-rest/ai-inference";
|
|
384
|
+
import { DefaultAzureCredential } from "@azure/identity";
|
|
398
385
|
|
|
399
|
-
|
|
400
|
-
|
|
386
|
+
const endpoint = "https://myaccount.openai.azure.com/";
|
|
387
|
+
const client = ModelClient(endpoint, new DefaultAzureCredential());
|
|
388
|
+
|
|
389
|
+
const url =
|
|
390
|
+
"https://upload.wikimedia.org/wikipedia/commons/thumb/d/dd/Gfp-wisconsin-madison-the-nature-boardwalk.jpg/2560px-Gfp-wisconsin-madison-the-nature-boardwalk.jpg";
|
|
391
|
+
const messages = [
|
|
392
|
+
{
|
|
393
|
+
role: "user",
|
|
394
|
+
content: [
|
|
395
|
+
{
|
|
396
|
+
type: "image_url",
|
|
397
|
+
image_url: {
|
|
398
|
+
url,
|
|
399
|
+
detail: "auto",
|
|
400
|
+
},
|
|
401
|
+
},
|
|
402
|
+
],
|
|
403
|
+
},
|
|
404
|
+
{ role: "user", content: "describe the image" },
|
|
405
|
+
];
|
|
401
406
|
|
|
402
|
-
```js
|
|
403
407
|
const response = await client.path("/chat/completions").post({
|
|
404
408
|
body: {
|
|
405
|
-
messages
|
|
409
|
+
messages,
|
|
410
|
+
},
|
|
406
411
|
});
|
|
407
|
-
|
|
412
|
+
|
|
413
|
+
if (isUnexpected(response)) {
|
|
414
|
+
throw response.body.error;
|
|
415
|
+
}
|
|
416
|
+
console.log(`Chatbot: ${response.body.choices[0].message?.content}`);
|
|
408
417
|
```
|
|
409
418
|
|
|
410
419
|
### Text Embeddings example
|
|
411
420
|
|
|
412
421
|
This example demonstrates how to get text embeddings with Entra ID authentication.
|
|
413
422
|
|
|
414
|
-
```
|
|
423
|
+
```ts snippet:ReadmeSample_TextEmbeddings
|
|
415
424
|
import ModelClient, { isUnexpected } from "@azure-rest/ai-inference";
|
|
416
425
|
import { DefaultAzureCredential } from "@azure/identity";
|
|
417
426
|
|
|
418
|
-
const endpoint = "
|
|
419
|
-
const
|
|
427
|
+
const endpoint = "https://myaccount.openai.azure.com/";
|
|
428
|
+
const client = ModelClient(endpoint, new DefaultAzureCredential());
|
|
420
429
|
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
},
|
|
427
|
-
});
|
|
430
|
+
const response = await client.path("/embeddings").post({
|
|
431
|
+
body: {
|
|
432
|
+
input: ["first phrase", "second phrase", "third phrase"],
|
|
433
|
+
},
|
|
434
|
+
});
|
|
428
435
|
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
}
|
|
436
|
+
if (isUnexpected(response)) {
|
|
437
|
+
throw response.body.error;
|
|
438
|
+
}
|
|
439
|
+
for (const data of response.body.data) {
|
|
440
|
+
console.log(
|
|
441
|
+
`data length: ${data.embedding.length}, [${data[0]}, ${data[1]}, ..., ${data[data.embedding.length - 2]}, ${data[data.embedding.length - 1]}]`,
|
|
442
|
+
);
|
|
437
443
|
}
|
|
438
|
-
|
|
439
|
-
main().catch((err) => {
|
|
440
|
-
console.error("The sample encountered an error:", err);
|
|
441
|
-
});
|
|
442
444
|
```
|
|
443
445
|
|
|
444
446
|
The length of the embedding vector depends on the model, but you should see something like this:
|
|
@@ -455,17 +457,17 @@ To generate embeddings for additional phrases, simply call `client.path("/embedd
|
|
|
455
457
|
|
|
456
458
|
This example demonstrates how to get image embeddings with Entra ID authentication.
|
|
457
459
|
|
|
458
|
-
```
|
|
459
|
-
import ModelClient, { isUnexpected } from "@azure-rest/ai-inference";
|
|
460
|
+
```ts snippet:ReadmeSample_ImageEmbeddings
|
|
460
461
|
import { DefaultAzureCredential } from "@azure/identity";
|
|
461
|
-
import
|
|
462
|
+
import { readFileSync } from "node:fs";
|
|
463
|
+
import ModelClient, { isUnexpected } from "@azure-rest/ai-inference";
|
|
462
464
|
|
|
463
|
-
const endpoint = "
|
|
465
|
+
const endpoint = "https://myaccount.openai.azure.com/";
|
|
464
466
|
const credential = new DefaultAzureCredential();
|
|
465
467
|
|
|
466
468
|
function getImageDataUrl(imageFile, imageFormat) {
|
|
467
469
|
try {
|
|
468
|
-
const imageBuffer =
|
|
470
|
+
const imageBuffer = readFileSync(imageFile);
|
|
469
471
|
const imageBase64 = imageBuffer.toString("base64");
|
|
470
472
|
return `data:image/${imageFormat};base64,${imageBase64}`;
|
|
471
473
|
} catch (error) {
|
|
@@ -475,28 +477,22 @@ function getImageDataUrl(imageFile, imageFormat) {
|
|
|
475
477
|
}
|
|
476
478
|
}
|
|
477
479
|
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
});
|
|
480
|
+
const client = ModelClient(endpoint, credential);
|
|
481
|
+
const image = getImageDataUrl("<image_file>", "<image_format>");
|
|
482
|
+
const response = await client.path("/images/embeddings").post({
|
|
483
|
+
body: {
|
|
484
|
+
input: [{ image }],
|
|
485
|
+
},
|
|
486
|
+
});
|
|
486
487
|
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
}
|
|
488
|
+
if (isUnexpected(response)) {
|
|
489
|
+
throw response.body.error;
|
|
490
|
+
}
|
|
491
|
+
for (const data of response.body.data) {
|
|
492
|
+
console.log(
|
|
493
|
+
`data length: ${data.embedding.length}, [${data[0]}, ${data[1]}, ..., ${data[data.embedding.length - 2]}, ${data[data.embedding.length - 1]}]`,
|
|
494
|
+
);
|
|
495
495
|
}
|
|
496
|
-
|
|
497
|
-
main().catch((err) => {
|
|
498
|
-
console.error("The sample encountered an error:", err);
|
|
499
|
-
});
|
|
500
496
|
```
|
|
501
497
|
|
|
502
498
|
The length of the embedding vector depends on the model, but you should see something like this:
|
|
@@ -514,11 +510,11 @@ To enable instrumentation, it is required to register exporter(s).
|
|
|
514
510
|
|
|
515
511
|
Here is an example to add console as a exporter:
|
|
516
512
|
|
|
517
|
-
```
|
|
513
|
+
```ts snippet:ReadmeSample_Instrumentation
|
|
518
514
|
import {
|
|
519
|
-
ConsoleSpanExporter,
|
|
520
515
|
NodeTracerProvider,
|
|
521
516
|
SimpleSpanProcessor,
|
|
517
|
+
ConsoleSpanExporter,
|
|
522
518
|
} from "@opentelemetry/sdk-trace-node";
|
|
523
519
|
|
|
524
520
|
const provider = new NodeTracerProvider();
|
|
@@ -528,7 +524,7 @@ provider.register();
|
|
|
528
524
|
|
|
529
525
|
Here is an example to add application insight to be a exporter:
|
|
530
526
|
|
|
531
|
-
```
|
|
527
|
+
```ts snippet:ReadmeSample_InstrumentationAppInsights
|
|
532
528
|
import { NodeTracerProvider, SimpleSpanProcessor } from "@opentelemetry/sdk-trace-node";
|
|
533
529
|
import { AzureMonitorTraceExporter } from "@azure/monitor-opentelemetry-exporter";
|
|
534
530
|
|
|
@@ -545,32 +541,39 @@ provider.register();
|
|
|
545
541
|
|
|
546
542
|
To use instrumentation for Azure SDK, you need to register it before importing any dependencies from `@azure/core-tracing`, such as `@azure-rest/ai-inference`.
|
|
547
543
|
|
|
548
|
-
```
|
|
544
|
+
```ts snippet:ReadmeSample_InstrumentationImport
|
|
549
545
|
import { registerInstrumentations } from "@opentelemetry/instrumentation";
|
|
550
546
|
import { createAzureSdkInstrumentation } from "@azure/opentelemetry-instrumentation-azure-sdk";
|
|
551
547
|
|
|
552
548
|
registerInstrumentations({
|
|
553
549
|
instrumentations: [createAzureSdkInstrumentation()],
|
|
554
550
|
});
|
|
555
|
-
|
|
556
|
-
import ModelClient from "@azure-rest/ai-inference";
|
|
557
551
|
```
|
|
558
552
|
|
|
559
|
-
Finally when you are making a call for chat completion, you need to include
|
|
553
|
+
Finally when you are making a call for chat completion, you need to include the `tracingOptions` in the request. Here is an example:
|
|
560
554
|
|
|
561
|
-
```
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
}
|
|
565
|
-
```
|
|
555
|
+
```ts snippet:ReadmeSample_InstrumentationRequest
|
|
556
|
+
import { DefaultAzureCredential } from "@azure/identity";
|
|
557
|
+
import ModelClient from "@azure-rest/ai-inference";
|
|
558
|
+
import { context } from "@opentelemetry/api";
|
|
566
559
|
|
|
567
|
-
|
|
560
|
+
const endpoint = "https://myaccount.openai.azure.com/";
|
|
561
|
+
const credential = new DefaultAzureCredential();
|
|
562
|
+
const client = ModelClient(endpoint, credential);
|
|
563
|
+
|
|
564
|
+
const messages = [
|
|
565
|
+
// NOTE: "system" role is not supported on all Azure Models
|
|
566
|
+
{ role: "system", content: "You are a helpful assistant. You will talk like a pirate." },
|
|
567
|
+
{ role: "user", content: "Can you help me?" },
|
|
568
|
+
{ role: "assistant", content: "Arrrr! Of course, me hearty! What can I do for ye?" },
|
|
569
|
+
{ role: "user", content: "What's the best way to train a parrot?" },
|
|
570
|
+
];
|
|
568
571
|
|
|
569
|
-
```js
|
|
570
|
-
import { context } from "@opentelemetry/api";
|
|
571
572
|
client.path("/chat/completions").post({
|
|
572
|
-
|
|
573
|
-
|
|
573
|
+
body: {
|
|
574
|
+
messages,
|
|
575
|
+
},
|
|
576
|
+
tracingOptions: { tracingContext: context.active() },
|
|
574
577
|
});
|
|
575
578
|
```
|
|
576
579
|
|
|
@@ -578,12 +581,13 @@ client.path("/chat/completions").post({
|
|
|
578
581
|
|
|
579
582
|
Open Telemetry provides `startActiveSpan` to instrument you own code. Here is an example:
|
|
580
583
|
|
|
581
|
-
```
|
|
584
|
+
```ts snippet:ReadmeSample_TracingOwnFunction
|
|
582
585
|
import { trace } from "@opentelemetry/api";
|
|
586
|
+
|
|
583
587
|
const tracer = trace.getTracer("sample", "0.1.0");
|
|
584
588
|
|
|
585
589
|
const getWeatherFunc = (location: string, unit: string): string => {
|
|
586
|
-
return tracer.startActiveSpan("getWeatherFunc", span => {
|
|
590
|
+
return tracer.startActiveSpan("getWeatherFunc", (span) => {
|
|
587
591
|
if (unit !== "celsius") {
|
|
588
592
|
unit = "fahrenheit";
|
|
589
593
|
}
|
|
@@ -592,7 +596,7 @@ const getWeatherFunc = (location: string, unit: string): string => {
|
|
|
592
596
|
span.end();
|
|
593
597
|
return result;
|
|
594
598
|
});
|
|
595
|
-
}
|
|
599
|
+
};
|
|
596
600
|
```
|
|
597
601
|
|
|
598
602
|
## Troubleshooting
|
|
@@ -601,8 +605,8 @@ const getWeatherFunc = (location: string, unit: string): string => {
|
|
|
601
605
|
|
|
602
606
|
Enabling logging may help uncover useful information about failures. In order to see a log of HTTP requests and responses, set the `AZURE_LOG_LEVEL` environment variable to `info`. Alternatively, logging can be enabled at runtime by calling `setLogLevel` in the `@azure/logger`:
|
|
603
607
|
|
|
604
|
-
```
|
|
605
|
-
|
|
608
|
+
```ts snippet:SetLogLevel
|
|
609
|
+
import { setLogLevel } from "@azure/logger";
|
|
606
610
|
|
|
607
611
|
setLogLevel("info");
|
|
608
612
|
```
|