Geração de anúncios aprimorada por IA usando o Azure Cosmos DB para MongoDB vCore

Neste guia, demonstramos como criar conteúdo de publicidade dinâmico que ressoe com seu público, usando nosso assistente de IA personalizado, Heelie. Utilizando o Azure Cosmos DB para MongoDB vCore, aproveitamos a funcionalidade de pesquisa de semelhança vetorial para analisar semanticamente e combinar descrições de inventário com tópicos de publicidade. O processo é possível através da geração de vetores para descrições de inventário usando incorporações OpenAI, que melhoram significativamente sua profundidade semântica. Esses vetores são então armazenados e indexados no recurso vCore do Cosmos DB for MongoDB. Ao gerar conteúdo para anúncios, vetorizamos o tópico do anúncio para encontrar os itens de inventário que melhor se adequam. Isso é seguido por um processo de geração aumentada de recuperação (RAG), onde as principais correspondências são enviadas para a OpenAI para criar um anúncio atraente. Toda a base de código do aplicativo está disponível em um repositório GitHub para sua referência.

Funcionalidades

  • Pesquisa de semelhança vetorial: usa o Azure Cosmos DB para a poderosa pesquisa de semelhança vetorial do MongoDB vCore para melhorar os recursos de pesquisa semântica, facilitando a localização de itens de inventário relevantes com base no conteúdo dos anúncios.
  • OpenAI Embeddings: Utiliza as incorporações de ponta da OpenAI para gerar vetores para descrições de inventário. Essa abordagem permite correspondências mais matizadas e semanticamente ricas entre o inventário e o conteúdo do anúncio.
  • Geração de conteúdo: Emprega os modelos de linguagem avançados da OpenAI para gerar anúncios envolventes e focados em tendências. Este método garante que o conteúdo não é apenas relevante, mas também cativante para o público-alvo.

Pré-requisitos

  • Azure OpenAI: Vamos configurar o recurso Azure OpenAI. Atualmente, o acesso a este serviço está disponível apenas por aplicativo. Você pode solicitar acesso ao Azure OpenAI preenchendo o formulário em https://aka.ms/oai/access. Depois de ter acesso, conclua as seguintes etapas:

    • Crie um recurso do Azure OpenAI seguindo este início rápido.
    • Implantar um completions e um embeddings modelo
      • Para mais informações sobre completionso , clique aqui.
      • Para mais informações sobre embeddingso , clique aqui.
    • Anote seus nomes de ponto de extremidade, chave e implantação.
  • Cosmos DB for MongoDB vCore resource: Vamos começar criando um recurso vCore do Azure Cosmos DB para MongoDB gratuitamente seguindo este guia de início rápido.

    • Anote os detalhes da conexão (cadeia de conexão).
  • Ambiente Python (>= versão 3.9) com pacotes como numpy, openai, pymongo, , python-dotenv, azure-core, azure-cosmos, tenacitye gradio.

  • Transfira o ficheiro de dados e guarde-o numa pasta de dados designada.

Executando o script

Antes de mergulharmos na parte empolgante de gerar anúncios aprimorados por IA, precisamos configurar nosso ambiente. Essa configuração envolve a instalação dos pacotes necessários para garantir que nosso script seja executado sem problemas. Aqui está um guia passo-a-passo para preparar tudo.

1.1 Instalar pacotes necessários

Em primeiro lugar, precisamos instalar alguns pacotes Python. Abra o terminal e execute os seguintes comandos:

 pip install numpy
 pip install openai==1.2.3
 pip install pymongo
 pip install python-dotenv
 pip install azure-core
 pip install azure-cosmos
 pip install tenacity
 pip install gradio
 pip show openai

1.2 Configurando o OpenAI e o Cliente do Azure

Depois de instalar os pacotes necessários, a próxima etapa envolve a configuração de nossos clientes OpenAI e Azure para o script, o que é crucial para autenticar nossas solicitações para a API OpenAI e os serviços do Azure.

import json
import time
import openai

from dotenv import dotenv_values
from openai import AzureOpenAI

# Configure the API to use Azure as the provider
openai.api_type = "azure"
openai.api_key = "<AZURE_OPENAI_API_KEY>"  # Replace with your actual Azure OpenAI API key
openai.api_base = "https://<OPENAI_ACCOUNT_NAME>.openai.azure.com/"  # Replace with your OpenAI account name
openai.api_version = "2023-06-01-preview"

# Initialize the AzureOpenAI client with your API key, version, and endpoint
client = AzureOpenAI(
    api_key=openai.api_key,
    api_version=openai.api_version,
    azure_endpoint=openai.api_base
)

Arquitetura de soluções

Arquitetura da solução

2. Criando incorporações e configurando o Cosmos DB

Depois de configurar nosso ambiente e cliente OpenAI, passamos para a parte central de nosso projeto de geração de anúncios aprimorados por IA. O código a seguir cria incorporações vetoriais a partir de descrições de texto de produtos e configura nosso banco de dados no Azure Cosmos DB para MongoDB vCore para armazenar e pesquisar essas incorporações.

2.1 Criar incorporações

Para gerar anúncios atraentes, primeiro precisamos entender os itens em nosso inventário. Fazemos isso criando incorporações vetoriais a partir de descrições de nossos itens, o que nos permite capturar seu significado semântico de uma forma que as máquinas podem entender e processar. Veja como você pode criar incorporações vetoriais para uma descrição de item usando o Azure OpenAI:

import openai

def generate_embeddings(text):
    try:
        response = client.embeddings.create(
            input=text, model="text-embedding-ada-002")
        embeddings = response.data[0].embedding
        return embeddings
    except Exception as e:
        print(f"An error occurred: {e}")
        return None

embeddings = generate_embeddings("Shoes for San Francisco summer")

if embeddings is not None:
    print(embeddings)

A função usa uma entrada de texto — como uma descrição de produto — e usa o client.embeddings.create método da API OpenAI para gerar uma incorporação vetorial para esse texto. Estamos usando o text-embedding-ada-002 modelo aqui, mas você pode escolher outros modelos com base em suas necessidades. Se o processo for bem-sucedido, ele imprime as incorporações geradas; caso contrário, ele manipula exceções imprimindo uma mensagem de erro.

3. Conecte e configure o Cosmos DB para o MongoDB vCore

Com nossas incorporações prontas, a próxima etapa é armazená-las e indexá-las em um banco de dados que suporte a pesquisa de semelhança vetorial. O Azure Cosmos DB para MongoDB vCore é perfeito para essa tarefa porque foi criado especificamente para armazenar seus dados transacionais e executar pesquisas vetoriais em um só lugar.

3.1 Configurar a ligação

Para nos conectarmos ao Cosmos DB, usamos a biblioteca pymongo, que nos permite interagir com o MongoDB facilmente. O trecho de código a seguir estabelece uma conexão com nossa instância vCore do Cosmos DB for MongoDB:

import pymongo

# Replace <USERNAME>, <PASSWORD>, and <VCORE_CLUSTER_NAME> with your actual credentials and cluster name
mongo_conn = "mongodb+srv://<USERNAME>:<PASSWORD>@<VCORE_CLUSTER_NAME>.mongocluster.cosmos.azure.com/?tls=true&authMechanism=SCRAM-SHA-256&retrywrites=false&maxIdleTimeMS=120000"
mongo_client = pymongo.MongoClient(mongo_conn)

Substitua <USERNAME>, <PASSWORD>e <VCORE_CLUSTER_NAME> pelo seu nome de usuário, senha e nome de cluster vCore reais do MongoDB, respectivamente.

4. Configurando o banco de dados e o índice vetorial no Cosmos DB

Depois de estabelecer uma conexão com o Azure Cosmos DB, as próximas etapas envolvem configurar seu banco de dados e coleção e, em seguida, criar um índice vetorial para habilitar pesquisas eficientes de semelhança vetorial. Vamos percorrer estas etapas.

4.1 Configurar o banco de dados e a coleção

Primeiro, criamos um banco de dados e uma coleção em nossa instância do Cosmos DB. Eis como:

DATABASE_NAME = "AdgenDatabase"
COLLECTION_NAME = "AdgenCollection"

mongo_client.drop_database(DATABASE_NAME)
db = mongo_client[DATABASE_NAME]
collection = db[COLLECTION_NAME]

if COLLECTION_NAME not in db.list_collection_names():
    # Creates a unsharded collection that uses the DBs shared throughput
    db.create_collection(COLLECTION_NAME)
    print("Created collection '{}'.\n".format(COLLECTION_NAME))
else:
    print("Using collection: '{}'.\n".format(COLLECTION_NAME))

4.2 Criar o índice vetorial

Para realizar pesquisas eficientes de semelhança vetorial dentro de nossa coleção, precisamos criar um índice vetorial. O Cosmos DB suporta diferentes tipos de índices vetoriais, e aqui discutimos dois: FIV e HNSW.

FIV

IVF significa Inverted File Index, é o algoritmo de indexação vetorial padrão, que funciona em todas as camadas de cluster. É uma abordagem de vizinhos mais próximos aproximados (ANN) que usa clustering para acelerar a busca por vetores semelhantes em um conjunto de dados. Para criar um índice de FIV, use o seguinte comando:

db.command({
  'createIndexes': COLLECTION_NAME,
  'indexes': [
    {
      'name': 'vectorSearchIndex',
      'key': {
        "contentVector": "cosmosSearch"
      },
      'cosmosSearchOptions': {
        'kind': 'vector-ivf',
        'numLists': 1,
        'similarity': 'COS',
        'dimensions': 1536
      }
    }
  ]
});

Importante

Você só pode criar um índice por propriedade de vetor. Ou seja, você não pode criar mais de um índice que aponte para a mesma propriedade vetorial. Se você quiser alterar o tipo de índice (por exemplo, de FIV para HNSW), você deve descartar o índice primeiro antes de criar um novo índice.

HNSW

HNSW significa Hierarchical Navigable Small World, uma estrutura de dados baseada em gráficos que particiona vetores em clusters e subclusters. Com o HNSW, você pode realizar pesquisas rápidas e aproximadas de vizinhos mais próximos em velocidades mais altas com maior precisão. HNSW é um método aproximado (ANN). Veja como configurá-lo:

db.command(
{ 
    "createIndexes": "ExampleCollection",
    "indexes": [
        {
            "name": "VectorSearchIndex",
            "key": {
                "contentVector": "cosmosSearch"
            },
            "cosmosSearchOptions": { 
                "kind": "vector-hnsw", 
                "m": 16, # default value 
                "efConstruction": 64, # default value 
                "similarity": "COS", 
                "dimensions": 1536
            } 
        } 
    ] 
}
)

Nota

A indexação HNSW só está disponível em camadas de cluster M40 e superiores.

5. Inserir dados na recolha

Agora, insira os dados de inventário, que incluem descrições e suas incorporações vetoriais correspondentes, na coleção recém-criada. Para inserir dados em nossa coleção, usamos o insert_many() método fornecido pela pymongo biblioteca. O método permite inserir vários documentos na coleção ao mesmo tempo. Nossos dados são armazenados em um arquivo JSON, que carregaremos e depois inseriremos no banco de dados.

Baixe o arquivo shoes_with_vectors.json do repositório GitHub e armazene-o em um data diretório dentro da pasta do projeto.

data_file = open(file="./data/shoes_with_vectors.json", mode="r") 
data = json.load(data_file)
data_file.close()

result = collection.insert_many(data)

print(f"Number of data points added: {len(result.inserted_ids)}")

6. Pesquisa vetorial no Cosmos DB para MongoDB vCore

Com nossos dados carregados com sucesso, agora podemos aplicar o poder da pesquisa vetorial para encontrar os itens mais relevantes com base em uma consulta. O índice vetorial que criamos anteriormente nos permite realizar pesquisas semânticas em nosso conjunto de dados.

Para realizar uma pesquisa vetorial, definimos uma função vector_search que leva uma consulta e o número de resultados a retornar. A função gera um vetor para a consulta usando a generate_embeddings função que definimos anteriormente e, em seguida, usa a funcionalidade do $search Cosmos DB para encontrar os itens correspondentes mais próximos com base em suas incorporações vetoriais.

# Function to assist with vector search
def vector_search(query, num_results=3):
    
    query_vector = generate_embeddings(query)

    embeddings_list = []
    pipeline = [
        {
            '$search': {
                "cosmosSearch": {
                    "vector": query_vector,
                    "numLists": 1,
                    "path": "contentVector",
                    "k": num_results
                },
                "returnStoredSource": True }},
        {'$project': { 'similarityScore': { '$meta': 'searchScore' }, 'document' : '$$ROOT' } }
    ]
    results = collection.aggregate(pipeline)
    return results

6.2 Realizar consulta de pesquisa vetorial

Finalmente, executamos nossa função de pesquisa vetorial com uma consulta específica e processamos os resultados para exibi-los:

query = "Shoes for Seattle sweater weather"
results = vector_search(query, 3)

print("\nResults:\n")
for result in results: 
    print(f"Similarity Score: {result['similarityScore']}")  
    print(f"Title: {result['document']['name']}")  
    print(f"Price: {result['document']['price']}")  
    print(f"Material: {result['document']['material']}") 
    print(f"Image: {result['document']['img_url']}") 
    print(f"Purchase: {result['document']['purchase_url']}\n")

7. Geração de conteúdo de anúncio com GPT-4 e DALL. E

Combinamos todos os componentes desenvolvidos para criar anúncios atraentes, empregando o GPT-4 da OpenAI para texto e DALL· E 3 para imagens. Juntamente com os resultados da pesquisa vetorial, formam um anúncio completo. Também apresentamos o Heelie, nosso assistente inteligente, encarregado de criar slogans de anúncios envolventes. Através do próximo código, você verá a Heelie em ação, aprimorando nosso processo de criação de anúncios.

from openai import OpenAI

def generate_ad_title(ad_topic):
    system_prompt = '''
    You are Heelie, an intelligent assistant for generating witty and cativating tagline for online advertisement.
        - The ad campaign taglines that you generate are short and typically under 100 characters.
    '''

    user_prompt = f'''Generate a catchy, witty, and short sentence (less than 100 characters) 
                    for an advertisement for selling shoes for {ad_topic}'''
    messages=[
        {"role": "system", "content": system_prompt},
        {"role": "user", "content": user_prompt},
    ]

    response = client.chat.completions.create(
        model="gpt-4",
        messages=messages
    )
    
    return response.choices[0].message.content

def generate_ad_image(ad_topic):
    daliClient = OpenAI(
        api_key="<DALI_API_KEY>"
    )

    image_prompt = f'''
        Generate a photorealistic image of an ad campaign for selling {ad_topic}. 
        The image should be clean, with the item being sold in the foreground with an easily identifiable landmark of the city in the background.
        The image should also try to depict the weather of the location for the time of the year mentioned.
        The image should not have any generated text overlay.
    '''

    response = daliClient.images.generate(
        model="dall-e-3",
        prompt= image_prompt,
        size="1024x1024",
        quality="standard",
        n=1,
        )

    return response.data[0].url

def render_html_page(ad_topic):

    # Find the matching shoes from the inventory
    results = vector_search(ad_topic, 4)
    
    ad_header = generate_ad_title(ad_topic)
    ad_image_url = generate_ad_image(ad_topic)


    with open('./data/ad-start.html', 'r', encoding='utf-8') as html_file:
        html_content = html_file.read()

    html_content += f'''<header>
            <h1>{ad_header}</h1>
        </header>'''    

    html_content += f'''
            <section class="ad">
            <img src="{ad_image_url}" alt="Base Ad Image" class="ad-image">
        </section>'''

    for result in results: 
        html_content += f''' 
        <section class="product">
            <img src="{result['document']['img_url']}" alt="{result['document']['name']}" class="product-image">
            <div class="product-details">
                <h3 class="product-title" color="gray">{result['document']['name']}</h2>
                <p class="product-price">{"$"+str(result['document']['price'])}</p>
                <p class="product-description">{result['document']['description']}</p>
                <a href="{result['document']['purchase_url']}" class="buy-now-button">Buy Now</a>
            </div>
        </section>
        '''

    html_content += '''</article>
                    </body>
                    </html>'''

    return html_content

8. Juntando tudo

Para tornar nossa geração de anúncios interativa, empregamos Gradio, uma biblioteca Python para criar UIs web simples. Definimos uma interface do usuário que permite que os usuários insiram tópicos de anúncios e, em seguida, gere e exiba dinamicamente o anúncio resultante.

import gradio as gr

css = """
    button { background-color: purple; color: red; }
    <style>
    </style>
"""

with gr.Blocks(css=css, theme=gr.themes.Default(spacing_size=gr.themes.sizes.spacing_sm, radius_size="none")) as demo:
    subject = gr.Textbox(placeholder="Ad Keywords", label="Prompt for Heelie!!")
    btn = gr.Button("Generate Ad")
    output_html = gr.HTML(label="Generated Ad HTML")

    btn.click(render_html_page, [subject], output_html)

    btn = gr.Button("Copy HTML")

if __name__ == "__main__":
    demo.launch()   

Saída

Tela de saída

Próximo passo