Share via


Segurança de conteúdo de IA do Azure biblioteca de cliente para Python – versão 1.0.0

Segurança de conteúdo de IA do Azure deteta conteúdos gerados pelo utilizador e gerados por IA prejudiciais em aplicações e serviços. A Segurança do Conteúdo inclui APIs de texto e imagem que lhe permitem detetar material prejudicial:

  • API de Análise de Texto: analisa o texto para conteúdo sexual, violência, ódio e auto-dano com níveis de multi-gravidade.
  • API de Análise de Imagens: analisa imagens de conteúdo sexual, violência, ódio e auto-dano com níveis de multi-gravidade.
  • APIs de Gestão de Listas de Texto: os classificadores de IA predefinidos são suficientes para a maioria das necessidades de segurança de conteúdo; no entanto, poderá ter de analisar os termos específicos do seu caso de utilização. Pode criar listas de bloqueios de termos a utilizar com a API de Texto.

Documentação

Estão disponíveis várias documentação para o ajudar a começar

Introdução

Pré-requisitos

Instalar o pacote

pip install azure-ai-contentsafety

Autenticar o cliente

Obter o ponto final

Pode encontrar o ponto final do recurso de serviço Segurança de conteúdo de IA do Azure com o Portal do Azure ou a CLI do Azure:

# Get the endpoint for the Azure AI Content Safety service resource
az cognitiveservices account show --name "resource-name" --resource-group "resource-group-name" --query "properties.endpoint"

Criar um ContentSafetyClient/BlocklistClient com a chave de API

Para utilizar uma chave de API como parâmetro credential .

  • Passo 1: obter a chave de API. A chave de API pode ser encontrada no Portal do Azure ou ao executar o seguinte comando da CLI do Azure :

    az cognitiveservices account keys list --name "<resource-name>" --resource-group "<resource-group-name>"
    
  • Passo 2: passar a chave como uma cadeia para uma instância de AzureKeyCredential.

    from azure.core.credentials import AzureKeyCredential
    from azure.ai.contentsafety import ContentSafetyClient, BlocklistClient
    
    endpoint = "https://<my-custom-subdomain>.cognitiveservices.azure.com/"
    credential = AzureKeyCredential("<api_key>")
    content_safety_client = ContentSafetyClient(endpoint, credential)
    blocklist_client = BlocklistClient(endpoint, credential)
    

Criar um ContentSafetyClient/BlocklistClient com Microsoft Entra credencial de token de ID

  • Passo 1: Ativar Microsoft Entra ID para o recurso. Veja este documento Authenticate with Microsoft Entra ID (Autenticar com Microsoft Entra ID) para obter os passos para ativar Microsoft Entra ID do recurso.

    Os passos principais são:

    • Crie um recurso com um subdomínio personalizado.
    • Crie o Principal de Serviço e atribua-lhe a função de Utilizador dos Serviços Cognitivos.
  • Passo 2: defina os valores do ID de cliente, do ID do inquilino e do segredo do cliente da aplicação Microsoft Entra como variáveis de ambiente: AZURE_CLIENT_ID, AZURE_TENANT_ID, AZURE_CLIENT_SECRET.

    DefaultAzureCredential utilizará os valores destas variáveis de ambiente.

    from azure.identity import DefaultAzureCredential
    from azure.ai.contentsafety import ContentSafetyClient, BlocklistClient
    
    endpoint = "https://<my-custom-subdomain>.cognitiveservices.azure.com/"
    credential = DefaultAzureCredential()
    content_safety_client = ContentSafetyClient(endpoint, credential)
    blocklist_client = BlocklistClient(endpoint, credential)
    

Conceitos-chave

Funcionalidades disponíveis

Existem diferentes tipos de análise disponíveis neste serviço. A tabela seguinte descreve as APIs atualmente disponíveis.

Funcionalidade Descrição
API de Análise de Texto Analisa texto para conteúdo sexual, violência, ódio e auto-mutilação com níveis de multi-gravidade.
API de Análise de Imagens Analisa imagens de conteúdo sexual, violência, ódio e auto-mutilação com níveis de multi-gravidade.
APIs de Gestão de Listas de Texto Os classificadores de IA predefinidos são suficientes para a maioria das necessidades de segurança de conteúdo. No entanto, poderá ter de analisar os termos específicos do seu caso de utilização. Pode criar listas de bloqueios de termos a utilizar com a API de Texto.

Categorias de danos

A Content Safety reconhece quatro categorias distintas de conteúdo censurável.

Categoria Descrição
Ódio Os danos relacionados com o ódio e a justiça referem-se a qualquer conteúdo que ataque ou utilize linguagem pejorativa ou discriminatória com referência a uma pessoa ou grupo de identidade com base em certos atributos diferenciadores destes grupos, incluindo, mas não se limitando à raça, etnia, nacionalidade, identidade e expressão de género, orientação sexual, religião, estatuto de imigração, estatuto de capacidade, aparência pessoal e tamanho do corpo.
Sexual Sexual descreve linguagem relacionada com órgãos anatómicos e genitais, relações românticas, atos retratados em termos eróticos ou afectuosos, gravidez, atos sexuais físicos, incluindo aqueles retratados como uma agressão ou um ato violento sexual forçado contra a sua vontade, prostituição, pornografia e abuso.
Violência A violência descreve a linguagem relacionada com ações físicas destinadas a ferir, ferir, danificar ou matar alguém ou algo assim; descreve armas, armas e entidades relacionadas, tais como fabricantes, associações, legislação, etc.
Auto-dano O auto-dano descreve a linguagem relacionada com ações físicas destinadas a magoar, ferir, danificar o corpo ou matar-se a si próprio.

A classificação pode ser com várias etiquetas. Por exemplo, quando uma amostra de texto passa pelo modelo de moderação de texto, pode ser classificada como Conteúdo sexual e Violência.

Níveis de gravidade

Todas as categorias de danos que o serviço aplica também têm uma classificação de nível de gravidade. O nível de gravidade destina-se a indicar a gravidade das consequências de mostrar o conteúdo sinalizado.

Texto: a versão atual do modelo de texto suporta a escala de gravidade 0-7 completa. Por predefinição, a resposta irá produzir 4 valores: 0, 2, 4 e 6. Cada dois níveis adjacentes são mapeados para um único nível. Os utilizadores podem utilizar "outputType" no pedido e defini-lo como "EightSeverityLevels" para obter 8 valores na saída: 0,1,2,3,4,5,6,7. Pode consultar definições de níveis de gravidade de conteúdo de texto para obter detalhes.

  • [0,1] -> 0
  • [2,3] -> 2
  • [4,5] -> 4
  • [6,7] -> 6

Imagem: A versão atual do modelo de imagem suporta a versão cortada da escala de gravidade 0-7 completa. O classificador só devolve gravidades 0, 2, 4 e 6; cada dois níveis adjacentes são mapeados para um único nível. Pode consultar definições de níveis de gravidade de conteúdo de imagem para obter detalhes.

  • [0,1] -> 0
  • [2,3] -> 2
  • [4,5] -> 4
  • [6,7] -> 6

Gestão da lista de bloqueios de texto

As seguintes operações são suportadas para gerir a lista de bloqueios de texto:

  • Criar ou modificar uma lista de bloqueios
  • Listar todas as listas de bloqueios
  • Obter uma lista de bloqueios por blocklistName
  • Adicionar blocklistItems a uma lista de bloqueios
  • Remover blocklistItems de uma lista de bloqueios
  • Listar todos os blocklistItems numa lista de bloqueios por blocklistName
  • Obter um blocklistItem numa lista de bloqueios por blocklistItemId e blocklistName
  • Eliminar uma lista de bloqueios e todos os seus blocklistItems

Pode definir as listas de bloqueio que pretende utilizar quando analisar texto e, em seguida, pode obter o resultado da correspondência da lista de bloqueios da resposta devolvida.

Exemplos

A secção seguinte fornece vários fragmentos de código que abrangem algumas das tarefas mais comuns do serviço de Segurança de Conteúdos, incluindo:

Veja os dados de exemplo dos dados utilizados aqui. Para obter mais exemplos, veja exemplos.

Analisar texto

Analisar texto sem listas de bloqueio


    import os
    from azure.ai.contentsafety import ContentSafetyClient
    from azure.ai.contentsafety.models import TextCategory
    from azure.core.credentials import AzureKeyCredential
    from azure.core.exceptions import HttpResponseError
    from azure.ai.contentsafety.models import AnalyzeTextOptions

    key = os.environ["CONTENT_SAFETY_KEY"]
    endpoint = os.environ["CONTENT_SAFETY_ENDPOINT"]

    # Create a Content Safety client
    client = ContentSafetyClient(endpoint, AzureKeyCredential(key))

    # Construct a request
    request = AnalyzeTextOptions(text="You are an idiot")

    # Analyze text
    try:
        response = client.analyze_text(request)
    except HttpResponseError as e:
        print("Analyze text failed.")
        if e.error:
            print(f"Error code: {e.error.code}")
            print(f"Error message: {e.error.message}")
            raise
        print(e)
        raise

    hate_result = next(item for item in response.categories_analysis if item.category == TextCategory.HATE)
    self_harm_result = next(item for item in response.categories_analysis if item.category == TextCategory.SELF_HARM)
    sexual_result = next(item for item in response.categories_analysis if item.category == TextCategory.SEXUAL)
    violence_result = next(item for item in response.categories_analysis if item.category == TextCategory.VIOLENCE)

    if hate_result:
        print(f"Hate severity: {hate_result.severity}")
    if self_harm_result:
        print(f"SelfHarm severity: {self_harm_result.severity}")
    if sexual_result:
        print(f"Sexual severity: {sexual_result.severity}")
    if violence_result:
        print(f"Violence severity: {violence_result.severity}")

Analisar texto com listas de bloqueio


    import os
    from azure.ai.contentsafety import ContentSafetyClient
    from azure.core.credentials import AzureKeyCredential
    from azure.ai.contentsafety.models import AnalyzeTextOptions
    from azure.core.exceptions import HttpResponseError

    key = os.environ["CONTENT_SAFETY_KEY"]
    endpoint = os.environ["CONTENT_SAFETY_ENDPOINT"]

    # Create a Content Safety client
    client = ContentSafetyClient(endpoint, AzureKeyCredential(key))

    blocklist_name = "TestBlocklist"
    input_text = "I h*te you and I want to k*ll you."

    try:
        # After you edit your blocklist, it usually takes effect in 5 minutes, please wait some time before analyzing with blocklist after editing.
        analysis_result = client.analyze_text(
            AnalyzeTextOptions(text=input_text, blocklist_names=[blocklist_name], halt_on_blocklist_hit=False)
        )
        if analysis_result and analysis_result.blocklists_match:
            print("\nBlocklist match results: ")
            for match_result in analysis_result.blocklists_match:
                print(
                    f"BlocklistName: {match_result.blocklist_name}, BlockItemId: {match_result.blocklist_item_id}, "
                    f"BlockItemText: {match_result.blocklist_item_text}"
                )
    except HttpResponseError as e:
        print("\nAnalyze text failed: ")
        if e.error:
            print(f"Error code: {e.error.code}")
            print(f"Error message: {e.error.message}")
            raise
        print(e)
        raise

Analisar imagem


    import os
    from azure.ai.contentsafety import ContentSafetyClient
    from azure.ai.contentsafety.models import ImageCategory
    from azure.core.credentials import AzureKeyCredential
    from azure.core.exceptions import HttpResponseError
    from azure.ai.contentsafety.models import AnalyzeImageOptions, ImageData

    key = os.environ["CONTENT_SAFETY_KEY"]
    endpoint = os.environ["CONTENT_SAFETY_ENDPOINT"]
    image_path = os.path.abspath(os.path.join(os.path.abspath(__file__), "..", "./sample_data/image.jpg"))

    # Create a Content Safety client
    client = ContentSafetyClient(endpoint, AzureKeyCredential(key))

    # Build request
    with open(image_path, "rb") as file:
        request = AnalyzeImageOptions(image=ImageData(content=file.read()))

    # Analyze image
    try:
        response = client.analyze_image(request)
    except HttpResponseError as e:
        print("Analyze image failed.")
        if e.error:
            print(f"Error code: {e.error.code}")
            print(f"Error message: {e.error.message}")
            raise
        print(e)
        raise

    hate_result = next(item for item in response.categories_analysis if item.category == ImageCategory.HATE)
    self_harm_result = next(item for item in response.categories_analysis if item.category == ImageCategory.SELF_HARM)
    sexual_result = next(item for item in response.categories_analysis if item.category == ImageCategory.SEXUAL)
    violence_result = next(item for item in response.categories_analysis if item.category == ImageCategory.VIOLENCE)

    if hate_result:
        print(f"Hate severity: {hate_result.severity}")
    if self_harm_result:
        print(f"SelfHarm severity: {self_harm_result.severity}")
    if sexual_result:
        print(f"Sexual severity: {sexual_result.severity}")
    if violence_result:
        print(f"Violence severity: {violence_result.severity}")

Gerir lista de bloqueios de texto

Criar ou atualizar a lista de bloqueios de texto


    import os
    from azure.ai.contentsafety import BlocklistClient
    from azure.ai.contentsafety.models import TextBlocklist
    from azure.core.credentials import AzureKeyCredential
    from azure.core.exceptions import HttpResponseError

    key = os.environ["CONTENT_SAFETY_KEY"]
    endpoint = os.environ["CONTENT_SAFETY_ENDPOINT"]

    # Create a Blocklist client
    client = BlocklistClient(endpoint, AzureKeyCredential(key))

    blocklist_name = "TestBlocklist"
    blocklist_description = "Test blocklist management."

    try:
        blocklist = client.create_or_update_text_blocklist(
            blocklist_name=blocklist_name,
            options=TextBlocklist(blocklist_name=blocklist_name, description=blocklist_description),
        )
        if blocklist:
            print("\nBlocklist created or updated: ")
            print(f"Name: {blocklist.blocklist_name}, Description: {blocklist.description}")
    except HttpResponseError as e:
        print("\nCreate or update text blocklist failed: ")
        if e.error:
            print(f"Error code: {e.error.code}")
            print(f"Error message: {e.error.message}")
            raise
        print(e)
        raise

Listar listas de bloqueios de texto


    import os
    from azure.ai.contentsafety import BlocklistClient
    from azure.core.credentials import AzureKeyCredential
    from azure.core.exceptions import HttpResponseError

    key = os.environ["CONTENT_SAFETY_KEY"]
    endpoint = os.environ["CONTENT_SAFETY_ENDPOINT"]

    # Create a Blocklist client
    client = BlocklistClient(endpoint, AzureKeyCredential(key))

    try:
        blocklists = client.list_text_blocklists()
        if blocklists:
            print("\nList blocklists: ")
            for blocklist in blocklists:
                print(f"Name: {blocklist.blocklist_name}, Description: {blocklist.description}")
    except HttpResponseError as e:
        print("\nList text blocklists failed: ")
        if e.error:
            print(f"Error code: {e.error.code}")
            print(f"Error message: {e.error.message}")
            raise
        print(e)
        raise

Obter lista de bloqueios de texto


    import os
    from azure.ai.contentsafety import BlocklistClient
    from azure.core.credentials import AzureKeyCredential
    from azure.core.exceptions import HttpResponseError

    key = os.environ["CONTENT_SAFETY_KEY"]
    endpoint = os.environ["CONTENT_SAFETY_ENDPOINT"]

    # Create a Blocklist client
    client = BlocklistClient(endpoint, AzureKeyCredential(key))

    blocklist_name = "TestBlocklist"

    try:
        blocklist = client.get_text_blocklist(blocklist_name=blocklist_name)
        if blocklist:
            print("\nGet blocklist: ")
            print(f"Name: {blocklist.blocklist_name}, Description: {blocklist.description}")
    except HttpResponseError as e:
        print("\nGet text blocklist failed: ")
        if e.error:
            print(f"Error code: {e.error.code}")
            print(f"Error message: {e.error.message}")
            raise
        print(e)
        raise

Eliminar lista de bloqueios de texto


    import os
    from azure.ai.contentsafety import BlocklistClient
    from azure.core.credentials import AzureKeyCredential
    from azure.core.exceptions import HttpResponseError

    key = os.environ["CONTENT_SAFETY_KEY"]
    endpoint = os.environ["CONTENT_SAFETY_ENDPOINT"]

    # Create a Blocklist client
    client = BlocklistClient(endpoint, AzureKeyCredential(key))

    blocklist_name = "TestBlocklist"

    try:
        client.delete_text_blocklist(blocklist_name=blocklist_name)
        print(f"\nDeleted blocklist: {blocklist_name}")
    except HttpResponseError as e:
        print("\nDelete blocklist failed:")
        if e.error:
            print(f"Error code: {e.error.code}")
            print(f"Error message: {e.error.message}")
            raise
        print(e)
        raise

Adicionar blockItems


    import os
    from azure.ai.contentsafety import BlocklistClient
    from azure.ai.contentsafety.models import AddOrUpdateTextBlocklistItemsOptions, TextBlocklistItem
    from azure.core.credentials import AzureKeyCredential
    from azure.core.exceptions import HttpResponseError

    key = os.environ["CONTENT_SAFETY_KEY"]
    endpoint = os.environ["CONTENT_SAFETY_ENDPOINT"]

    # Create a Blocklist client
    client = BlocklistClient(endpoint, AzureKeyCredential(key))

    blocklist_name = "TestBlocklist"
    block_item_text_1 = "k*ll"
    block_item_text_2 = "h*te"

    block_items = [TextBlocklistItem(text=block_item_text_1), TextBlocklistItem(text=block_item_text_2)]
    try:
        result = client.add_or_update_blocklist_items(
            blocklist_name=blocklist_name, options=AddOrUpdateTextBlocklistItemsOptions(blocklist_items=block_items)
        )
        for block_item in result.blocklist_items:
            print(
                f"BlockItemId: {block_item.blocklist_item_id}, Text: {block_item.text}, Description: {block_item.description}"
            )
    except HttpResponseError as e:
        print("\nAdd block items failed: ")
        if e.error:
            print(f"Error code: {e.error.code}")
            print(f"Error message: {e.error.message}")
            raise
        print(e)
        raise

Listar blockItems


    import os
    from azure.ai.contentsafety import BlocklistClient
    from azure.core.credentials import AzureKeyCredential
    from azure.core.exceptions import HttpResponseError

    key = os.environ["CONTENT_SAFETY_KEY"]
    endpoint = os.environ["CONTENT_SAFETY_ENDPOINT"]

    # Create a Blocklist client
    client = BlocklistClient(endpoint, AzureKeyCredential(key))

    blocklist_name = "TestBlocklist"

    try:
        block_items = client.list_text_blocklist_items(blocklist_name=blocklist_name)
        if block_items:
            print("\nList block items: ")
            for block_item in block_items:
                print(
                    f"BlockItemId: {block_item.blocklist_item_id}, Text: {block_item.text}, "
                    f"Description: {block_item.description}"
                )
    except HttpResponseError as e:
        print("\nList block items failed: ")
        if e.error:
            print(f"Error code: {e.error.code}")
            print(f"Error message: {e.error.message}")
            raise
        print(e)
        raise

Obter blockItem


    import os
    from azure.ai.contentsafety import BlocklistClient
    from azure.core.credentials import AzureKeyCredential
    from azure.ai.contentsafety.models import TextBlocklistItem, AddOrUpdateTextBlocklistItemsOptions
    from azure.core.exceptions import HttpResponseError

    key = os.environ["CONTENT_SAFETY_KEY"]
    endpoint = os.environ["CONTENT_SAFETY_ENDPOINT"]

    # Create a Blocklist client
    client = BlocklistClient(endpoint, AzureKeyCredential(key))

    blocklist_name = "TestBlocklist"
    block_item_text_1 = "k*ll"

    try:
        # Add a blockItem
        add_result = client.add_or_update_blocklist_items(
            blocklist_name=blocklist_name,
            options=AddOrUpdateTextBlocklistItemsOptions(blocklist_items=[TextBlocklistItem(text=block_item_text_1)]),
        )
        if not add_result or not add_result.blocklist_items or len(add_result.blocklist_items) <= 0:
            raise RuntimeError("BlockItem not created.")
        block_item_id = add_result.blocklist_items[0].blocklist_item_id

        # Get this blockItem by blockItemId
        block_item = client.get_text_blocklist_item(blocklist_name=blocklist_name, blocklist_item_id=block_item_id)
        print("\nGet blockitem: ")
        print(
            f"BlockItemId: {block_item.blocklist_item_id}, Text: {block_item.text}, Description: {block_item.description}"
        )
    except HttpResponseError as e:
        print("\nGet block item failed: ")
        if e.error:
            print(f"Error code: {e.error.code}")
            print(f"Error message: {e.error.message}")
            raise
        print(e)
        raise

Remover blockItems


    import os
    from azure.ai.contentsafety import BlocklistClient
    from azure.core.credentials import AzureKeyCredential
    from azure.ai.contentsafety.models import (
        TextBlocklistItem,
        AddOrUpdateTextBlocklistItemsOptions,
        RemoveTextBlocklistItemsOptions,
    )
    from azure.core.exceptions import HttpResponseError

    key = os.environ["CONTENT_SAFETY_KEY"]
    endpoint = os.environ["CONTENT_SAFETY_ENDPOINT"]

    # Create a Blocklist client
    client = BlocklistClient(endpoint, AzureKeyCredential(key))

    blocklist_name = "TestBlocklist"
    block_item_text_1 = "k*ll"

    try:
        # Add a blockItem
        add_result = client.add_or_update_blocklist_items(
            blocklist_name=blocklist_name,
            options=AddOrUpdateTextBlocklistItemsOptions(blocklist_items=[TextBlocklistItem(text=block_item_text_1)]),
        )
        if not add_result or not add_result.blocklist_items or len(add_result.blocklist_items) <= 0:
            raise RuntimeError("BlockItem not created.")
        block_item_id = add_result.blocklist_items[0].blocklist_item_id

        # Remove this blockItem by blockItemId
        client.remove_blocklist_items(
            blocklist_name=blocklist_name, options=RemoveTextBlocklistItemsOptions(blocklist_item_ids=[block_item_id])
        )
        print(f"\nRemoved blockItem: {add_result.blocklist_items[0].blocklist_item_id}")
    except HttpResponseError as e:
        print("\nRemove block item failed: ")
        if e.error:
            print(f"Error code: {e.error.code}")
            print(f"Error message: {e.error.message}")
            raise
        print(e)
        raise

Resolução de problemas

Geral

Segurança de conteúdo de IA do Azure biblioteca de cliente irá gerar exceções definidas no Azure Core. Os códigos de erro são definidos como abaixo:

Código de Erro Motivos possíveis Sugestões
InvalidRequestBody Um ou mais campos no corpo do pedido não correspondem à definição da API. 1. Verifique a versão da API que especificou na chamada à API.
2. Verifique a definição da API correspondente para a versão da API que selecionou.
InvalidResourceName O nome do recurso especificado no URL não cumpre os requisitos, como o nome da lista de bloqueios, o ID do termo da lista de bloqueios, etc. 1. Verifique a versão da API que especificou na chamada à API.
2. Verifique se o nome especificado tem carateres inválidos de acordo com a definição da API.
ResourceNotFound O recurso que especificou no URL pode não existir, como o nome da lista de bloqueios. 1. Verifique a versão da API que especificou na chamada à API.
2. Verifique novamente a existência do recurso especificado no URL.
InternalError Algumas situações inesperadas no lado do servidor foram acionadas. 1. Poderá querer repetir algumas vezes após um pequeno período e ver que o problema volta a ocorrer.
2. Contacte o Suporte do Azure se este problema persistir.
ServerBusy O lado do servidor não consegue processar o pedido temporariamente. 1. Poderá querer repetir algumas vezes após um pequeno período e ver que o problema volta a ocorrer.
2.Contacte o Suporte do Azure se este problema persistir.
TooManyRequests O RPS atual excedeu a quota do SKU atual. 1. Verifique a tabela de preços para compreender a quota de RPS.
2.Contacte o Suporte do Azure se precisar de mais QPS.

Registo

Esta biblioteca utiliza a biblioteca de registos padrão para registos.

As informações básicas sobre as sessões HTTP (URLs, cabeçalhos, etc.) são registadas ao INFO nível.

O registo de nível detalhado DEBUG , incluindo os corpos de pedido/resposta e cabeçalhos não retotados , pode ser ativado no cliente ou por operação com o logging_enable argumento palavra-chave.

Veja a documentação completa do registo do SDK com exemplos aqui.

Configuração opcional

Os argumentos de palavra-chave opcionais podem ser transmitidos ao nível do cliente e por operação. A documentação de referência do azure-core descreve as configurações disponíveis para repetições, registos, protocolos de transporte e muito mais.

Passos seguintes

Documentação adicional

Para obter documentação mais extensa sobre a Segurança de Conteúdos do Azure, veja o Segurança de conteúdo de IA do Azure no docs.microsoft.com.

Contribuir

Agradecemos todas as contribuições e sugestões para este projeto. A maioria das contribuições requerem que celebre um Contrato de Licença de Contribuição (CLA) no qual se declare que tem o direito de conceder e que, na verdade, concede-nos os direitos para utilizar a sua contribuição. Para mais detalhes, visite https://cla.microsoft.com.

Quando submete um pedido Pull, um bot do CLA determina automaticamente se tem de fornecer um CLA e decorar o PR de forma adequada (por exemplo, etiqueta, comentário). Só tem de seguir as instruções fornecidas pelo bot. Apenas terá de fazer isto uma vez em todos os repositórios com o nosso CLA.

Este projeto adotou o Microsoft Open Source Code of Conduct (Código de Conduta do Microsoft Open Source). Para obter mais informações, veja a Code of Conduct FAQ (FAQ do Código de Conduta) ou envie um e-mail para opencode@microsoft.com com quaisquer perguntas ou comentários adicionais.