File: migration_guide.md

package info (click to toggle)
python-azure 20250603%2Bgit-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 851,724 kB
  • sloc: python: 7,362,925; ansic: 804; javascript: 287; makefile: 195; sh: 145; xml: 109
file content (493 lines) | stat: -rw-r--r-- 19,808 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
# Guide for migrating to azure-ai-language-questionanswering from azure-cognitiveservices-knowledge-qnamaker

This guide is intended to assist in the migration to [azure-ai-language-questionanswering](https://pypi.org/project/azure-ai-language-questionanswering/) from the old one [azure-cognitiveservices-knowledge-qnamaker](https://pypi.org/project/azure-cognitiveservices-knowledge-qnamaker/). It will focus on side-by-side comparisons for similar operations between the two packages.

Familiarity with the `azure-cognitiveservices-knowledge-qnamaker` package is assumed. For those new to the Question Answering client library for Python, please refer to the [README for azure-ai-language-questionanswering][qna_readme] rather than this guide.

## Table of contents
  - [Migration benefits](#migration-benefits)
  - [General changes](#general-changes)
    - [Package and namespaces](#package-and-namespaces)
    - [Runtime Client](#runtime-client)
      - [Authenticating runtime client](#authenticating-runtime-client)
      - [Querying a question](#querying-a-question)
      - [Chatting](#chatting)
    - [Authoring Client](#authoring-client)
      - [Authenticating authoring client](#authenticating-authoring-client)
      - [Creating knowledge base](#creating-knowledge-base)
      - [Updating knowledge base](#updating-knowledge-base)
      - [Exporting knowledge base](#exporting-knowledge-base)
      - [Deleting knowledge base](#deleting-knowledge-base)
  - [Async operations](#async-operations)
  - [Additional Samples](#additional-samples)

## Migration benefits

A natural question to ask when considering whether or not to adopt a new version or library is what the benefits of doing so would be. As Azure has matured and been embraced by a more diverse group of developers, we have been focused on learning the patterns and practices to best support developer productivity and to understand the gaps that the Python client libraries have.

There were several areas of consistent feedback expressed across the Azure client library ecosystem. One of the most important is that the client libraries for different Azure services have not had a consistent approach to organization, naming, and API structure. Additionally, many developers have felt that the learning curve was difficult, and the APIs did not offer a good, approachable, and consistent onboarding story for those learning Azure or exploring a specific Azure service.

To try and improve the development experience across Azure services, a set of uniform [design guidelines][design_guidelines] was created for all languages to drive a consistent experience with established API patterns for all services. A set of [Python-specific guidelines][python_specific_guidelines] was also introduced to ensure that Python clients have a natural and idiomatic feel with respect to the Python ecosystem. Further details are available in the guidelines for those interested.

## General changes

The modern Question Answering client library provides the ability to share in some of the cross-service improvements made to the Azure development experience, such as
- using the new [azure-identity][identity_readme] library to share a single authentication approach between clients
- a unified logging and diagnostics pipeline offering a common view of the activities across each of the client libraries

### Package and namespaces

Package names and the namespace root for the modern Azure Cognitive Services client libraries for Python have changed. Each will follow the pattern `azure.ai.[services]` where the legacy clients followed the pattern `azure.cognitiveservices.[services]`. This provides a quick and accessible means to help understand, at a glance, whether you are using the modern or legacy clients.

In the case of Question Answering, the modern client libraries have packages and namespaces that begin with `azure.ai.language.questionanswering` and were released beginning with version 1. The legacy client libraries have packages and namespaces that begin with `azure.cognitiveservices.knowledge.qnamaker` and a version of 0.3.0 or below.

### Runtime Client

#### Authenticating runtime client

Previously in `azure-cognitiveservices-knowledge-qnamaker` you could create a `QnAMakerClient` by using `CognitiveServicesCredentials` from `msrest.authentication`:

```python
from msrest.authentication import CognitiveServicesCredentials
from azure.cognitiveservices.knowledge.qnamaker import QnAMakerClient

client = QnAMakerClient(
    endpoint="https://<my-cognitiveservices-account>.cognitiveservices.azure.com",
    credentials=CognitiveServicesCredentials("API key")
)
```

Now in `azure-ai-language-questionanswering` you can create a `QuestionAnsweringClient` using an [AzureKeyCredential][azure_key_credential] or a token credential from the [azure-identity](https://pypi.org/project/azure-identity/) library:

```python
from azure.core.credentials import AzureKeyCredential
from azure.ai.language.questionanswering import QuestionAnsweringClient

client = QuestionAnsweringClient(
    endpoint="https://<my-cognitiveservices-account>.cognitiveservices.azure.com",
    credential=AzureKeyCredential("API key")
)
```

```python
from azure.identity import DefaultAzureCredential
from azure.ai.language.questionanswering import QuestionAnsweringClient

client = QuestionAnsweringClient(
    endpoint="https://<my-cognitiveservices-account>.cognitiveservices.azure.com",
    credential=DefaultAzureCredential()
)
```

#### Querying a question

In `azure-cognitiveservices-knowledge-qnamaker`, you could query for a question using `QueryDTO`:

```python
from azure.cognitiveservices.knowledge.qnamaker.models import QueryDTO
from azure.cognitiveservices.knowledge.qnamaker import QnAMakerClient

client = QnAMakerClient(endpoint, credentials)

generate_answer_payload = QueryDTO(
    question="How long should my Surface battery last?",
)

response = client.knowledgebase.generate_answer(
    kb_id="<my-knowledge-base-id>",
    generate_answer_payload=generate_answer_payload,
)
best_answers = [a for a in response.answers if a.score > 0.9]
```

In the modern `azure-ai-language-questionanswering`, you use `get_answers`:

```python
from azure.ai.language.questionanswering import QuestionAnsweringClient

client = QuestionAnsweringClient(endpoint=endpoint, credential=credential)

response = client.get_answers(
    question="How long should my Surface battery last?",
    project_name="<my-qna-project-name>",
    deployment_name="<my-qna-deployment-name>"
)
best_answers = [a for a in response.answers if a.confidence_score > 0.9]
```

#### Chatting

Previously in `azure-cognitiveservices-knowledge-qnamaker`, you could chat using `QueryDTO` along with setting the context to have `previous_qna_id`:

```python
from azure.cognitiveservices.knowledge.qnamaker.models import QueryDTO, QueryDTOContext
from azure.cognitiveservices.knowledge.qnamaker import QnAMakerClient

client = QnAMakerClient(endpoint, credentials)

generate_answer_payload = QueryDTO(
    question="How long should my Surface battery last?",
    context=QueryDTOContext(previous_qna_id=1)
)

response = client.knowledgebase.generate_answer(
    kb_id="<my-knowledge-base-id>",
    generate_answer_payload=generate_answer_payload,
)
best_answers = [a for a in response.answers if a.score > 0.9]
```

Now in `azure-ai-language-questionanswering`, you use `KnowledgeBaseAnswerContext`  to set `project_name`, `deployment_name`, and `question` along with setting the `answer_context` to have `previous_qna_id`:


```python
from azure.ai.language.questionanswering import QuestionAnsweringClient
from azure.ai.language.questionanswering.models import KnowledgeBaseAnswerContext

client = QuestionAnsweringClient(endpoint=endpoint, credential=credential)

response = client.get_answers(
    question="How long should my Surface battery last?",
    project_name="<my-qna-project-name>",
    deployment_name="<my-qna-deployment-name>",
    answer_context=KnowledgeBaseAnswerContext(
        previous_qna_id=1
    )
)

best_answers = [a for a in response.answers if a.confidence_score > 0.9]
```

### Authoring Client

#### Authenticating authoring client

Previously in `azure-cognitiveservices-knowledge-qnamaker` you could create a `QnAMakerClient` by using `CognitiveServicesCredentials` from `msrest.authentication`:

```python
from msrest.authentication import CognitiveServicesCredentials
from azure.cognitiveservices.knowledge.qnamaker import QnAMakerClient

client = QnAMakerClient(
    endpoint="https://<my-cognitiveservices-account>.cognitiveservices.azure.com",
    credentials=CognitiveServicesCredentials("API key")
)
```

Now in `azure-ai-language-questionanswering` you can create a `AuthoringClient` using an [AzureKeyCredential][azure_key_credential] or a token credential from the [azure-identity](https://pypi.org/project/azure-identity/) library:

```python
from azure.core.credentials import AzureKeyCredential
from azure.ai.language.questionanswering.authoring import AuthoringClient

client = AuthoringClient(
    endpoint="https://<my-cognitiveservices-account>.cognitiveservices.azure.com",
    credential=AzureKeyCredential("API key")
)
```

```python
from azure.identity import DefaultAzureCredential
from azure.ai.language.questionanswering.authoring import AuthoringClient

client = AuthoringClient(
    endpoint="https://<my-cognitiveservices-account>.cognitiveservices.azure.com",
    credential=DefaultAzureCredential()
)
```

#### Creating knowledge base

Previously in `azure-cognitiveservices-knowledge-qnamaker`, you could create a new knowledgebase using a `CreateKbDTO`:

```python
import time
from msrest.authentication import CognitiveServicesCredentials
from azure.cognitiveservices.knowledge.qnamaker.models import CreateKbDTO, QnADTO
from azure.cognitiveservices.knowledge.qnamaker import QnAMakerClient

client = QnAMakerClient(
    endpoint="https://<my-cognitiveservices-account>.cognitiveservices.azure.com",
    credentials=CognitiveServicesCredentials("API key")
)

operation = client.knowledgebase.create(
    create_kb_payload=CreateKbDTO(
        name="<knowledgebase-name>",
        qna_list=[
            QnADTO(
                questions=["questions"],
                answer="answer"
            )
        ]
        
    )
)
for i in range(20):
    if operation.operation_state in ["NotStarted", "Running"]:
        print("Waiting for operation: {} to complete.".format(operation.operation_id))
        time.sleep(5)
        operation = client.operations.get_details(operation_id=operation.operation_id)
    else:
        break

if operation.operation_state != "Succeeded":
    raise Exception("Operation {} failed to complete.".format(operation.operation_id))

# Get knowledge base ID from resourceLocation HTTP header
knowledge_base_id = operation.resource_location.replace("/knowledgebases/", "")
print("Created KB with ID: {}".format(knowledge_base_id))
```

Now in `azure-ai-language-questionanswering`, you can create a new Question Answering project by passing a `dict` with the needed project creation properties:

```python
from azure.core.credentials import AzureKeyCredential
from azure.ai.language.questionanswering.authoring import AuthoringClient

client = AuthoringClient(
    endpoint="https://<my-cognitiveservices-account>.cognitiveservices.azure.com",
    credential=AzureKeyCredential("API key")
)

project = client.create_project(
    project_name="<project_name>",
    options={
        "description": "This is the description for a test project",
        "language": "en",
        "multilingualResource": True,
        "settings": {
            "defaultAnswer": "no answer"
        }
    })

print(f"Project name: {project['projectName']}")
print(f"language: {project['language']}")
print(f"description: {project['description']}")
```

#### Updating knowledge base

Previously in `azure-cognitiveservices-knowledge-qnamaker`, you could update your knowledge base using a `UpdateKbOperationDTO`:

```python
import time
from msrest.authentication import CognitiveServicesCredentials
from azure.cognitiveservices.knowledge.qnamaker.models import UpdateKbOperationDTO, UpdateKbOperationDTOAdd, QnADTO
from azure.cognitiveservices.knowledge.qnamaker import QnAMakerClient

client = QnAMakerClient(
    endpoint="https://<my-cognitiveservices-account>.cognitiveservices.azure.com",
    credentials=CognitiveServicesCredentials("API key")
)

operation = client.knowledgebase.update(
    kb_id="<knowledgebase-id>",
    update_kb=UpdateKbOperationDTO(
        add=UpdateKbOperationDTOAdd(
            qna_list=[
                QnADTO(
                    questions=["questions"],
                    answer="answer"
                )
            ]
        )   
    )
)
for i in range(20):
    if operation.operation_state in ["NotStarted", "Running"]:
        print("Waiting for operation: {} to complete.".format(operation.operation_id))
        time.sleep(5)
        operation = client.operations.get_details(operation_id=operation.operation_id)
    else:
        break

if operation.operation_state != "Succeeded":
    raise Exception("Operation {} failed to complete.".format(operation.operation_id))

# Get knowledge base ID from resourceLocation HTTP header
knowledge_base_id = operation.resource_location.replace("/knowledgebases/", "")
print("Created KB with ID: {}".format(knowledge_base_id))
```

Now in `azure-ai-language-questionanswering`, you can update your knowledge source using the `begin_update_sources` method:

```python
from azure.core.credentials import AzureKeyCredential
from azure.ai.language.questionanswering.authoring import AuthoringClient

client = AuthoringClient(
    endpoint="https://<my-cognitiveservices-account>.cognitiveservices.azure.com",
    credential=AzureKeyCredential("API key")
)

sources_poller = client.begin_update_sources(
    project_name="<project_name>",
    sources=[{
        "op": "add",
        "value": {
            "displayName": "MicrosoftFAQ",
            "source": "https://www.microsoft.com/en-in/software-download/faq",
            "sourceUri": "https://www.microsoft.com/en-in/software-download/faq",
            "sourceKind": "url",
            "contentStructureKind": "unstructured",
            "refresh": False
        }
    }]
)
sources = sources_poller.result()

for item in sources:
    print(f"source name: {item.get('displayName', 'N/A')}")
    print(f"\tsource: {item['source']}")
    print(f"\tsource uri: {item.get('sourceUri', 'N/A')}")
    print(f"\tsource kind: {item['sourceKind']}")
```

You can also update a project's questions and answers directly as follows:

```python
from azure.core.credentials import AzureKeyCredential
from azure.ai.language.questionanswering.authoring import AuthoringClient

client = AuthoringClient(
    endpoint="https://<my-cognitiveservices-account>.cognitiveservices.azure.com",
    credential=AzureKeyCredential("API key")
)

qna_poller = client.begin_update_qnas(
    project_name="<project_name>",
    qnas=[{
        "op": "add",
        "value": {
            "questions": [
                "What is the easiest way to use Azure services in my Python project?"
            ],
            "answer": "Using the Azure SDKs"
        }
    }]
)

qnas = qna_poller.result()

for item in qnas:
    print(f"qna: {item['id']}")
    print("\tquestions:")
    for question in item["questions"]:
        print(f"\t\t{question}")
    print(f"\tanswer: {item['answer']}")
```

#### Exporting knowledge base

Previously in `azure-cognitiveservices-knowledge-qnamaker`, you could download your knowledge base using the `download` method:

```python
from msrest.authentication import CognitiveServicesCredentials
from azure.cognitiveservices.knowledge.qnamaker import QnAMakerClient

client = QnAMakerClient(
    endpoint="https://<my-cognitiveservices-account>.cognitiveservices.azure.com",
    credentials=CognitiveServicesCredentials("API key")
)

data = client.knowledgebase.download(
    kb_id="<knowledgebase-id>",
    environment="Test",
)
print(data.qna_documents)
```

Now you can export your Question Answering project:


```python
from azure.core.credentials import AzureKeyCredential
from azure.ai.language.questionanswering.authoring import AuthoringClient

client = AuthoringClient(
    endpoint="https://<my-cognitiveservices-account>.cognitiveservices.azure.com",
    credential=AzureKeyCredential("API key")
)

export_poller = client.begin_export(
    project_name="<project_name>",
    file_format="json"
)
export_result = export_poller.result()
export_url = export_result["resultUrl"]
```

#### Deleting knowledge base

Previously in `azure-cognitiveservices-knowledge-qnamaker`, you could delete your knowledge base using the `delete` method:

```python
from msrest.authentication import CognitiveServicesCredentials
from azure.cognitiveservices.knowledge.qnamaker import QnAMakerClient

client = QnAMakerClient(
    endpoint="https://<my-cognitiveservices-account>.cognitiveservices.azure.com",
    credentials=CognitiveServicesCredentials("API key")
)

client.knowledgebase.delete(
    kb_id="<knowledgebase-id>"
)
```

Now in `azure-ai-language-questionanswering`, you can delete a project using the `begin_delete_project` method:

```python
from azure.core.credentials import AzureKeyCredential
from azure.ai.language.questionanswering.authoring import AuthoringClient

client = AuthoringClient(
    endpoint="https://<my-cognitiveservices-account>.cognitiveservices.azure.com",
    credential=AzureKeyCredential("API key")
)

delete_poller = client.begin_delete_project(
    project_name="<project_name>",
)
delete_poller.result()
```

## Async operations

The modern `azure-ai-language-questionanswering` library includes a complete set of async APIs. To use it, you must first install an async transport, such as [aiohttp][aiohttp]. See [azure-core documentation][azure_core_transport] for more information.

Async operations are available on async clients, which should be closed when they're no longer needed. Each async client is an async context manager and defines an async `close` method. For example:

```python
from azure.core.credentials import AzureKeyCredential
from azure.ai.language.questionanswering.aio import QuestionAnsweringClient

endpoint = "https://<my-cognitiveservices-account>.cognitiveservices.azure.com"
credential = AzureKeyCredential("API key")

# call close when the client is no longer needed
client = QuestionAnsweringClient(endpoint=endpoint, credential=credential)
...
await client.close()

# alternatively, use the client as an async context manager
async with QuestionAnsweringClient(endpoint=endpoint, credential=credential) as client:
    ...
```


## Additional Samples

The new `azure-ai-language-questionanswering` has new capabilities not supported by the old client library, you can
see additional samples [here][qna_samples].

<!--LINKS-->
[qna_readme]: https://github.com/Azure/azure-sdk-for-python/blob/main/sdk/cognitivelanguage/azure-ai-language-questionanswering/README.md
[design_guidelines]: https://azure.github.io/azure-sdk/python/guidelines/index.html
[python_specific_guidelines]: https://azure.github.io/azure-sdk/python_design.html
[identity_readme]: https://github.com/Azure/azure-sdk-for-python/blob/main/sdk/identity/azure-identity/README.md
[azure_key_credential]: https://learn.microsoft.com/python/api/azure-core/azure.core.credentials.azurekeycredential?view=azure-python
[aiohttp]: https://pypi.org/project/aiohttp/
[azure_core_transport]: https://github.com/Azure/azure-sdk-for-python/blob/main/sdk/core/azure-core/CLIENT_LIBRARY_DEVELOPER.md#transport
[qna_samples]: https://github.com/Azure/azure-sdk-for-python/tree/main/sdk/cognitivelanguage/azure-ai-language-questionanswering/samples