#Vector Search

0 Seguidores · 33 Postagens

A busca em vetores é um método usado na recuperação de informações e no aprendizado de máquina para encontrar itens semelhantes com base nas representações matemáticas como vetores. Nessa abordagem, cada item é representado como um fator de muitas dimensões, sendo que cada uma corresponde a um aspecto ou característica do item. Depois, os algoritmos de busca em vetores comparam esses vetores para encontrar itens similares, por exemplo, que têm características parecidas ou estão próximos no espaço vetorial. Leia mais aqui.

Artigo Heloisa Paiva · Out. 7, 2025 2m read

Com a rápida adoção da telemedicina, consutlas remotas e digitação digital, profissionais da saúde estão se comunicano mais do que nunca por voz. Pacientes em conversas virtuais geram uma vasta quantidade de dados sonoros não estruturados, então como clínicos e administradores pesquisam e extraem informações d horas de gravações de voz? 

Apresentamos o IRIS Audio Query – um aplicativo full-stack que transforma áudio em uma base de conhecimento pesquisável. Com ele, você pode:

0
0 22
Anúncio Danusa Calixto · Out. 7, 2025

Olá Comunidade, 

Estamos felizes em compartilhar um novo tutorial do Instruqt: 

🧑‍🏫 RAG usando a Pesquisa Vetorial do InterSystems IRI

Este laboratório prático orienta você na construção de um chatbot de IA de Geração Aumentada de Recuperação (RAG) com tecnologia InterSystems IRIS Vector Search. Você verá como a pesquisa vetorial pode ser utilizada para fornecer respostas atualizadas e precisas, combinando os pontos fortes do IRIS com a IA generativa.

✨ Por que tentar?

0
0 13
InterSystems Oficial Danusa Calixto · Ago. 13, 2025

Olá Comunidade! 

Este é um desafio técnico aberto a todos os participantes do hackathon MIT Hacking Medicine:

Melhor Uso do GenAI com a Busca Vetorial da InterSystems

Ao encarar seu desafio na área da saúde neste fim de semana, pense em como a IA Generativa pode aumentar a eficácia e a inteligência da sua solução.

Siga os passos do repositório GitHub do InterSystems IRIS Vector Searchpara começar.

Os mentores da InterSystems estarão no local para ajudar você a começar e implementar.

Esperamos por vocês 😉

1
0 33
Anúncio Danusa Calixto · Jul. 29, 2025

#InterSystems Demo Games entry


⏯️ Care Compass – Assistente de IA RAG com tecnologia InterSystems IRIS para gerentes de cuidados

O Care Compass é um protótipo de assistente de IA que auxilia assistentes sociais a priorizar clientes por meio da análise de dados clínicos e sociais. Utilizando a Geração Aumentada de Recuperação (RAG) e modelos de linguagem de grande porte, ele gera resumos narrativos de risco, calcula pontuações de risco dinâmicas e recomenda os próximos passos. O objetivo é reduzir as visitas evitáveis ao pronto-socorro e apoiar intervenções precoces e informadas.

Apresentadores:
🗣 @Brad Nissenbaum, Sales Engineer, InterSystems
🗣 @Andrew Wardly, Sales Engineer, InterSystems
🗣 @Fan Ji, Solution Developer, InterSystems
🗣 @Lynn Wu, Sales Engineer, InterSystems

0
0 25
Artigo Henry Pereira · Maio 30, 2025 6m read

imagem

Sabe aquela sensação de receber o resultado do seu exame de sangue e parecer que está em grego? É exatamente esse problema que o FHIRInsight veio resolver. Surgiu da ideia de que dados médicos não deveriam ser assustadores ou confusos – deveriam ser algo que todos podemos utilizar. Exames de sangue são extremamente comuns para verificar nossa saúde, mas, sejamos sinceros, interpretá-los é difícil para a maioria das pessoas e, às vezes, até para profissionais da área que não trabalham em um laboratório. O FHIRInsight quer tornar todo esse processo mais simples e acessível.

Logo FHIRInsight

🤖 Por que criamos o FHIRInsight

Tudo começou com uma simples pergunta:

“Por que interpretar um exame de sangue ainda é tão difícil — até para médicos, às vezes?”

Se você já olhou para um resultado de laboratório, provavelmente viu um monte de números, abreviações enigmáticas e uma “faixa de referência” que pode ou não se aplicar à sua idade, sexo ou condição. É uma ferramenta de diagnóstico, com certeza — mas sem contexto, vira um jogo de adivinhação. Até profissionais de saúde experientes às vezes precisam recorrer a diretrizes, artigos científicos ou opiniões de especialistas para entender tudo direito.

É aí que o FHIRInsight entra em cena.

Não foi feito apenas para pacientes — fizemos para quem está na linha de frente do atendimento. Para médicos em plantões intermináveis, para enfermeiros que captam sutis padrões nos sinais vitais, para qualquer profissional de saúde que precise tomar decisões certas com tempo limitado e muita responsabilidade. Nosso objetivo é facilitar um pouco o trabalho deles — transformando dados clínicos FHIR em algo claro, útil e fundamentado em ciência médica real. Algo que fale a língua humana.

O FHIRInsight faz mais do que só explicar valores de exames. Ele também:

  • Fornece aconselhamento contextual sobre se um resultado é leve, moderado ou grave
  • Sugere causas potenciais e diagnósticos diferenciais com base em sinais clínicos
  • Recomenda próximos passos — sejam exames adicionais, encaminhamentos ou atendimento de urgência
  • Utiliza RAG (Retrieval-Augmented Generation) para incorporar artigos científicos relevantes que fundamentam a análise

Imagine um jovem médico revisando um hemograma de um paciente com anemia. Em vez de buscar cada valor no Google ou vasculhar revistas médicas, ele recebe um relatório que não só resume o problema, mas cita estudos recentes ou diretrizes da OMS que embasam o raciocínio. Esse é o poder de combinar IA e busca vetorial sobre pesquisas selecionadas.

E o paciente?

Ele não fica mais diante de um monte de números, sem saber o que significa “bilirrubina 2,3 mg/dL” ou se deve se preocupar. Em vez disso, recebe uma explicação simples e cuidadosa. Algo que se assemelha mais a uma conversa do que a um laudo clínico. Algo que ele realmente entende — e que pode levar ao consultório do médico mais preparado e menos ansioso.

Porque é disso que o FHIRInsight trata de verdade: transformar complexidade médica em clareza e ajudar profissionais e pacientes a tomarem decisões melhores e mais confiantes — juntos.

🔍 Por dentro da tecnologia

Claro que toda essa simplicidade na superfície é viabilizada por uma tecnologia poderosa atuando discretamente nos bastidores.

Veja do que o FHIRInsight é feito:

  • FHIR (Fast Healthcare Interoperability Resources) — padrão global de dados de saúde. É assim que recebemos informações estruturadas como resultados de exames, histórico do paciente, dados demográficos e atendimentos. O FHIR é a linguagem que os sistemas médicos falam — e nós traduzimos essa linguagem em algo que as pessoas possam usar.
  • Busca Vetorial RAG (Retrieval-Augmented Generation): o FHIRInsight aprimora seu raciocínio diagnóstico indexando artigos científicos em PDF e URLs confiáveis em um banco de dados usando a busca vetorial nativa do InterSystems IRIS. Quando um resultado de exame fica ambíguo ou complexo, o sistema recupera conteúdo relevante para embasar suas recomendações — não da memória do modelo, mas de pesquisas reais e atualizadas.
  • Engenharia de Prompts para Raciocínio Médico: refinamos nossos prompts para guiar o LLM na identificação de um amplo espectro de condições relacionadas ao sangue. Desde anemia por deficiência de ferro até coagulopatias, desequilíbrios hormonais ou gatilhos autoimunes — o prompt conduz o LLM pelas variações de sintomas, padrões laboratoriais e causas possíveis.
  • Integração com LiteLLM: um adaptador customizado direciona requisições para múltiplos provedores de LLM (OpenAI, Anthropic, Ollama etc.) através de uma interface unificada, permitindo fallback, streaming e troca de modelo com facilidade.

Tudo isso acontece em segundos — transformando valores brutos de laboratório em insights médicos explicáveis e acionáveis, seja para um médico revisando 30 prontuários ou um paciente tentando entender seus números.

🧩 o Adapter LiteLLM: Uma Interface para Todos os Modelos

Nos bastidores, os relatórios do FHIRInsight movidos a IA são impulsionados pelo LiteLLM — uma library python que nos permite chamar mais de 100 LLMs (OpenAI, Claude, Gemini, Ollama etc.) por meio de uma única interface estilo OpenAI.

Porém, integrar o LiteLLM ao InterSystems IRIS exigiu algo mais permanente e reutilizável do que scripts Python escondidos numa Business Operation. Então, criamos nosso próprio Adapter LiteLLM.

Conheça o LiteLLMAdapter

Esse adaptador lida com tudo o que você esperaria de uma integração robusta de LLM:

  • Recebe parâmetros como prompt, model e temperature
  • Carrega dinamicamente variáveis de ambiente (por exemplo, chaves de API)

Para encaixar isso em nossa produção de interoperabilidade em um simples Business Operation:

  • Gerencia configuração em produção por meio da configuração padrão LLMModel
  • Integra-se ao componente FHIRAnalyzer para geração de relatórios em tempo real
  • Atua como uma “ponte de IA” central para quaisquer componentes futuros que precisem de acesso a LLM

Eis o fluxo de forma simplificada:

set response = ##class(dc.LLM.LiteLLMAdapter).CallLLM("Me fale sobre hemoglobina.", "openai/gpt-4o", 0.7)
write response

🧪 Conclusão

Quando começamos a desenvolver o FHIRInsight, nossa missão era simples: tornar exames de sangue mais fáceis de entender — para todo mundo. Não apenas pacientes, mas médicos, enfermeiros, cuidadores... qualquer pessoa que já tenha encarado um resultado de laboratório e pensado: “Ok, mas o que isso realmente significa?”

Todos nós já passamos por isso.

Ao combinar a estrutura do FHIR, a velocidade do InterSystems IRIS, a inteligência dos LLMs e a profundidade de pesquisas médicas reais via busca vetorial, criamos uma ferramenta que transforma números confusos em histórias significativas. Histórias que ajudam pessoas a tomarem decisões mais inteligentes sobre sua saúde — e, quem sabe, detectar algo cedo que passaria despercebido.

Mas o FHIRInsight não é só sobre dados. É sobre como nos sentimos ao olhar para esses dados. Queremos que seja claro, acolhedor e empoderador. Que a experiência seja... como um verdadeiro “vibecoding” na saúde — aquele ponto perfeito onde código inteligente, bom design e empatia humana se encontram.

Esperamos que você experimente, teste, questione — e nos ajude a melhorar.

Diga o que gostaria de ver no próximo release. Mais condições? Mais explicações? Mais personalização?

Isso é só o começo — e adoraríamos que você ajudasse a moldar o que vem a seguir.

1
0 33
Artigo Heloisa Paiva · Maio 20, 2025 7m read

Este artigo apresenta uma solução em potencial para a busca semântica de código no TrakCare usando o IRIS Vector Search.

Aqui está uma breve visão geral dos resultados da busca semântica de código do TrakCare para a consulta: "Validação antes de salvar o objeto no banco de dados".

 

  • Modelo de Embedding de Código

Existem diversos modelos de embedding desenvolvidos para frases e parágrafos, mas eles não são ideais para embeddings específicos de código.

0
0 30
Artigo Heloisa Paiva · Abr. 3, 2025 4m read

No artigo anterior, apresentamos o aplicativo d[IA]gnosis, desenvolvido para auxiliar na codificação de diagnósticos na CID-10. Neste artigo, veremos como o InterSystems IRIS for Health nos fornece as ferramentas necessárias para a geração de vetores a partir da lista de códigos da CID-10, usando um modelo de linguagem pré-treinado, seu armazenamento e a subsequente busca por similaridades em todos esses vetores gerados.

Introdução

1
0 33
InterSystems Oficial Danusa Calixto · Mar. 27, 2025

InterSystems Anuncia Disponibilidade Geral do InterSystems IRIS, InterSystems IRIS for Health e HealthShare Health Connect 2025.1

A versão 2025.1 da plataforma de dados InterSystems IRIS®, InterSystems IRIS® for HealthTM e HealthShare® Health Connect agora está disponível para o público em geral (GA). Esta é uma versão de Manutenção Estendida (EM).

Destaques do Lançamento

Nesta versão emocionante, os usuários podem esperar vários novos recursos e melhorias, incluindo:

0
0 51
Artigo Julio Esquerdo · Fev. 11, 2025 7m read

Utilizando o Gateway SQL com Python, Vector Search e Interoperabilidade no InterSystems Iris

Parte 2 – Python e Vector Search

Uma vez que temos acesso aos dados da nossa tabela externa podemos utilizar tudo que o Iris tem de excelente com estes dados. Vamos, por exemplo, ler os dados da nossa tabela externa e gerar uma regressão polinomial com eles.

Para mais informações sobre o uso do python com o Iris veja a documentação disponível em https://docs.intersystems.com/irislatest/csp/docbook/DocBook.UI.Page.cls?KEY=AFL_epython

0
0 38
Artigo Julio Esquerdo · Fev. 11, 2025 4m read

Utilizando o Gateway SQL com Python, Vector Search e Interoperabilidade no InterSystems Iris

Parte 1 – Gateway SQL

Olá,

Neste artigo vamos ver o uso do Gateway SQL no Iris. O Gateway SQL permite que o Iris tenha acesso a tabelas de outros bancos (externos) via ODBC ou JDBC. Podemos acessar Tabelas ou Visões de diversos bancos, como Oracle, PostgreSQL, SQL Server, MySQL e outros.

Do ponto de vista de uso é como se a tabela estivesse local na nossa instância Iris, porém o armazenamento é realizado em um local externo.

0
0 57
Artigo Heloisa Paiva · Fev. 5, 2025 2m read

Você precisa instalar o aplicativo primeiro. Se não estiver instalado, por favor, consulte o artigo anterior.

Demonstração do aplicativo

Após executar com sucesso o aplicativo de busca de vetores de imagem de íris, alguns dados precisam ser armazenados para suportar a recuperação de imagens, pois não são inicializados na biblioteca.

Armazenamento de imagens

Primeiramente, arraste e solte a imagem ou clique no ícone de upload, selecione a imagem e clique no botão de upload para enviar e vetorizá-la. Este processo pode ser um pouco lento.

0
0 34
Artigo Heloisa Paiva · Fev. 1, 2025 2m read

Olá Comunidade,

Neste artigo, apresentarei meu aplicativo iris-image-vector-search.
A demonstração de recuperação de vetores de imagem usa IRIS Embedded Python e o modelo OpenAI CLIP para converter imagens em dados vetoriais de 512 dimensões. Através do novo recurso de Busca Vetorial, VECTOR-COSINE é usado para calcular a similaridade e exibir imagens de alta similaridade.

Direção de aplicação da recuperação de imagens

0
0 34
InterSystems Oficial Danusa Calixto · Nov. 28, 2024

InterSystems anuncia Disponibilidade Geral do InterSystems IRIS, InterSystems IRIS for Health, e HealthShare Health Connect 2024.3

A versão 2024.3 da plataforma de dados InterSystems IRIS® , InterSystems IRIS® for HealthTM, and HealthShare® Health Connect já está disponível para o público em geral.

Destaques da Versão

Nesta versão, você pode esperar uma série de atualizações interessantes, incluindo:

  1. Extensão muito mais rápida de arquivos de banco de dados e WIJ
  2. Capacidade de reenviar mensagens do Visual Trace
  3. Recursos aprimorados do Rule Editor
  4. Melhorias na pesquisa de vetores
  5. e mais.
0
0 48
Artigo Davi Massaru Teixeira Muta · Nov. 5, 2024 13m read

Utilizando IRIS - Vector Search

Assista ao vídeo explicativo com conteúdo deste tutorial.

<iframe width="560" height="315" src="https://www.youtube.com/embed/joLN9a8MY5c?si=3sO6EmjZADcPO3fO" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe> ## Estudo de Caso: Recomendação de Filmes

Este artigo explora o potencial do Vector Search do InterSystems IRIS em um estudo de caso para recomendação de filmes.

Serão demonstrados os passos necessários para o armazenamento e a consulta de registros no banco de dados InterSystems IRIS. Abordando a criação da tabela, armazenamento dos registros e a construção de uma aplicação de consulta, onde terá a disponibilização por meio do mais novo recurso WSGI.

Ao final, será desenvolvida uma aplicação Flask que utilizará o recurso Vector Search, implementada com embedded python e executada diretamente em um servidor IRIS.

Por que o Vector Search ?

Com o Vector Search no InterSystems IRIS permite armazenar e comparar os vetores, utilizando para identificar itens semanticamente semelhantes, o que amplia as capacidades de recomendação e recuperação de informações em diversos contextos.

No InterSystems IRIS, vetores são armazenados em tabelas como um tipo de dado específico %Vector, e funções como VECTOR_COSINE e VECTOR_DOT_PRODUCT são usadas para comparar a similaridade entre vetores. Esse recurso facilita a criação de sistemas de recomendação, permitindo que um texto vetorizado de entrada seja comparado com um conjunto de vetores armazenados para encontrar os mais semelhantes.

No caso de recomendação de filmes, por exemplo, podem ser transformadas em vetores utilizando modelos de linguagem, como os da biblioteca SentenceTransformer nas descrições de filmes, possibilitando uma recomendação por similaridade

DATA SET

O Dataset utilizado para este tutorial está contido em : https://www.kaggle.com/datasets/utkarshx27/movies-dataset

Criação da tabela.

Para iniciar o armazenamento dos dados, é necessário criar a tabela onde os filmes serão armazenados.

Como estamos utilizando o modelo SentenceTransformer('all-MiniLM-L6-v2'), será criada uma coluna específica, chamada overviewVector, para armazenar os vetores.

A coluna será definida com o tipo de dado %Vector(DATATYPE = "DOUBLE", LEN = 384), que permite armazenar vetores de 384 dimensões em formato de ponto flutuante.

Para isso, podemos rodar o sql:

CREATE TABLE dc.filmes (
    title VARCHAR(255),
    originalTitle VARCHAR(255),
    genres VARCHAR(255),
    overview VARCHAR(200000),
    keywords VARCHAR(255),
    director VARCHAR(255),
    popularity VARCHAR(255),
    productionCompanies VARCHAR(255),
    releaseDate VARCHAR(255),
    overviewVector VECTOR(DOUBLE, 384)
)

Ou realizar a criação codificando a classe .cls criando a seguinte estrutura de arquivo:

Class dc.filmes Extends %Persistent
{

Property title As %String(MAXLEN = "");

Property originalTitle As %String(MAXLEN = "");

Property director As %String(MAXLEN = "");

Property popularity As %String(MAXLEN = "");

Property releaseDate As %String(MAXLEN = "");

Property genres As %String(MAXLEN = "");

Property overview As %String(MAXLEN = "");

Property keywords As %String(MAXLEN = "");

Property productionCompanies As %String(MAXLEN = "");

Property overviewVector As %Vector(DATATYPE = "DOUBLE", LEN = 384);
}

VETORIZANDO

Neste caso, para o armazenamento dos dados, será utilizado o SentenceTransformer('all-MiniLM-L6-v2'), este modelo transforma frases (ou palavras) em um vetor de 384 elementos que capturam características semânticas da entrada, permitindo que a similaridade entre diferentes textos seja comparada através de operações como a distância ou o produto escalar entre vetores.


from sentence_transformers import SentenceTransformer
model = SentenceTransformer('all-MiniLM-L6-v2') 
overview = "Exemplo de frase para vetorizar"
encode_search_vector = model.encode(overview, normalize_embeddings=True).tolist()

Armazenado Vector com InterSystems IRIS

O código abaixo apresenta como podemos utilizar o Embedded Python para cadastrar os registros contidos no conjunto de dados (Data Set):

Class dc.util [ Language = python ]
{

ClassMethod PopularFilmes()
{
    import pandas as pd

    # PASSO 1: Lendo o arquivo .CSV.
    corpus_url = '/opt/irisbuild/movie_dataset.csv'
    df_original = pd.read_csv(corpus_url)
    data_frame = df_original[
        [
        'title',
        'original_title',
        'genres',
        'overview',
        'keywords',
        'director',
        'popularity',
        'production_companies',
        'release_date'
        ]
    ]

    # PASSO 2: Excluindo registros em branco "NaN".
    data_frame['overview'].replace("", float("NaN"), inplace=True)
    data_frame = data_frame.dropna(subset=['overview'])

    # PASSO 3: Aplicando o pré-processamento.
    def preprocess_text(descricao) : 
        import re
        from string import punctuation
        from unidecode import unidecode
        
        descricao = descricao.lower()
        descricao = unidecode(descricao)
        descricao = re.sub(r'\d+','', descricao)
        descricao = descricao.translate(str.maketrans('', '', punctuation))
        
        return descricao

    data_frame['overview_preprocessado'] = data_frame['overview'].apply(preprocess_text)

    # PASSO 4: Realizando o encode e criação dos vetores.
    print("Criando o modelo/realiznado encode")
    from sentence_transformers import SentenceTransformer
    model = SentenceTransformer('all-MiniLM-L6-v2')
    embeddings = model.encode(data_frame['overview_preprocessado'].tolist(), normalize_embeddings=True)
    data_frame['overview_vector'] = embeddings.tolist()

    # PASSO 5: Inserindo os registros no banco de dados.
    import iris
    print("Cadastrando Filmes")
    query = """
        INSERT INTO dc.filmes 
        (title,
        originalTitle,
        genres,
        overview,
        keywords,
        director,
        popularity,
        productionCompanies,
        releaseDate,
        overviewVector)
        VALUES (?,?,?,?,?,?,?,?,?,TO_VECTOR(?))
        """
    stmt = iris.sql.prepare(query)
    for index, row in data_frame.iterrows():
        rs = stmt.execute(
            row['title'],
            row['original_title'],
            row['genres'],
            row['overview'],
            row['keywords'],
            row['director'],
            row['popularity'],
            row['production_companies'],
            row['release_date'],
            str(row['overview_vector'])
        )
}

}

Observação:

Para realizar o armazenamento de registros do tipo %Vector, utiliza-se a função SQL TO_VECTOR(?), conforme mostrado no script abaixo:

INSERT INTO dc.filmes (overviewVector) VALUES (TO_VECTOR(?))

No código Python, é necessário converter o vetor de uma lista para uma string antes de inseri-lo no banco de dados. Isso é feito com a seguinte linha:

str(row['overview_vector'])

Ao executar o comando Do ##class(dc.util).PopularFilmes() em uma instância do InterSystems IRIS, os registros serão armazenados corretamente no banco de dados, permitindo consultas e operações de busca avançadas com base nos vetores armazenados.

Consultando Registros Similares

Após o armazenamento dos registros, utilizaremos a função VECTOR_DOT_PRODUCT.

Como descristo na documentação, a função VECTOR_DOT_PRODUCT encontra o produto escalar de dois vetores de entrada. Esses vetores devem ser do tipo numérico, inteiro, duplo ou decimal. O resultado é o valor do produto escalar, representado como um duplo, e pode ser útil ao tentar determinar a semelhança entre dois vetores.

O SQL a seguir busca os 5 filmes mais semelhantes a partir de um vetor fornecido, utilizando o produto escalar para medir a similaridade:

    SELECT TOP 5 ID
    FROM dc.filmes 
    WHERE ID <> ?
    ORDER BY VECTOR_DOT_PRODUCT(overviewVector, TO_VECTOR(?)) DESC 
  • SELECT TOP 5 ID: Retorna os 5 primeiros IDs na lista ordenada.
  • FROM dc.filmes: Consulta a tabela filmes no banco de dados.
  • WHERE ID <> ?: Exclui o ID fornecido da busca.
  • ORDER BY VECTOR_DOT_PRODUCT: Ordena os resultados pela similaridade entre o vetor overviewVector e o vetor gerado por TO_VECTOR(?), em ordem decrescente.

Essa abordagem permite que o sistema recomende filmes que são semanticamente próximos ao que foi fornecido como consulta, oferecendo sugestões mais relevantes para os usuários.

Exemplo da consulta script python:

import iris
from sentence_transformers import SentenceTransformer

# Abrindo o Registro desejado
filme = iris.cls("dc.filmes")._OpenId(id)

# Recriando vetor armazenado de overview
model = SentenceTransformer('all-MiniLM-L6-v2') 
overview_preprocess = preprocess_text(filme.overview)
encode_search_vector = model.encode(overview_preprocess, normalize_embeddings=True).tolist()

# Consulta SQL
query = """
    SELECT TOP 5 ID
    FROM dc.filmes 
    WHERE ID <> ?
    ORDER BY VECTOR_DOT_PRODUCT(overviewVector, TO_VECTOR(?)) DESC 
    """
stmt = iris.sql.prepare(query)
rs = stmt.execute(id, str(encode_search_vector))

# Visualização retorno da consulta
for idx, row in enumerate(rs):
    recomendacao = iris.cls("dc.filmes")._OpenId(row[0])
    print(recomendacao.title)

Codificando com flask e embedded python

Por fim, a disponibilização do recurso para o usuário final de maneira rápida e prática é facilitada pelo uso do Embedded Python do InterSystems IRIS. Utilizando o Flask, podemos criar um serviço em um único arquivo Python:

from flask import Flask, jsonify, request
from sentence_transformers import SentenceTransformer

import iris

app = Flask(__name__)

@app.route('/recomendar/<id>', methods=['GET'])
def consulta(id):
    try:

        filme = iris.cls("dc.filmes")._OpenId(id)
        model = SentenceTransformer('all-MiniLM-L6-v2') 
        overview_preprocess = iris.cls("dc.util").Preprocess(filme.overview)
        encode_search_vector = model.encode(overview_preprocess, normalize_embeddings=True).tolist()
        
        query = """
            SELECT TOP 5 ID
            FROM dc.filmes 
            WHERE ID <> ?
            ORDER BY VECTOR_DOT_PRODUCT(overviewVector, TO_VECTOR(?)) DESC 
            """
        similares = []
        stmt = iris.sql.prepare(query)
        rs = stmt.execute(id, str(encode_search_vector))
        for idx, row in enumerate(rs):
            recomendacao = iris.cls("dc.filmes")._OpenId(row[0])
            similares.append({
                "title" : recomendacao.title,
                "originalTitle" : recomendacao.originalTitle,
                "genres" : recomendacao.genres,
                "overview" : recomendacao.overview,
                "keywords" : str(recomendacao.keywords),
                "director" : recomendacao.director,
                "popularity" : recomendacao.popularity,
                "productionCompanies" : recomendacao.productionCompanies,
                "releaseDate" : recomendacao.releaseDate
            })

        return jsonify({ 
            "Filme":{
                "title" : filme.title,
                "originalTitle" : filme.originalTitle,
                "genres" : filme.genres,
                "overview" : filme.overview,
                "keywords" : str(filme.keywords),
                "director" : filme.director,
                "popularity" : filme.popularity,
                "productionCompanies" : filme.productionCompanies,
                "releaseDate" : filme.releaseDate
            },
            "Similares" : similares
        })
        
    except Exception as e:
        return print(e)

if __name__ == '__main__':
    app.run(debug=True, port=52773, host='localhost')

Resultado Final:

Por fim, após disponibilizar o recurso, prepare uma pipoca e utilize a rota:

http://localhost:52773/flaskapp/recomendar/<ID FILME>

Ao realizar a consulta, você receberá uma resposta em JSON semelhante a esta:

{
  "Filme": {
    "director": "Justin Lin",
    "genres": "Action Adventure Science Fiction",
    "keywords": "sequel stranded hatred space opera",
    "originalTitle": "Star Trek Beyond",
    "overview": "The USS Enterprise crew explores the furthest reaches of uncharted space, where they encounter a mysterious new enemy who puts them and everything the Federation stands for to the test.",
    "popularity": 65.352913,
    "productionCompanies": "[{\"name\": \"Paramount Pictures\", \"id\": 4}, {\"name\": \"Bad Robot\", \"id\": 11461}, {\"name\": \"Perfect Storm Entertainment\", \"id\": 34530}, {\"name\": \"Alibaba Pictures Group\", \"id\": 69484}, {\"name\": \"Skydance Media\", \"id\": 82819}, {\"name\": \"Sneaky Shark\", \"id\": 83644}, {\"name\": \"Huahua Media\", \"id\": 83645}]",
    "releaseDate": "2016-07-07",
    "title": "Star Trek Beyond"
  },
  "Similares": [
    {
      "director": "Robert Wise",
      "genres": "Science Fiction Adventure Mystery",
      "keywords": "artificial intelligence uss enterprise starfleet san francisco self sacrifice",
      "originalTitle": "Star Trek: The Motion Picture",
      "overview": "When a destructive space entity is spotted approaching Earth, Admiral Kirk resumes command of the Starship Enterprise in order to intercept, examine, and hopefully stop it.",
      "popularity": 24.616634,
      "productionCompanies": "[{\"name\": \"Paramount Pictures\", \"id\": 4}]",
      "releaseDate": "1979-12-06",
      "title": "Star Trek: The Motion Picture"
    },
    {
      "director": "Leonard Nimoy",
      "genres": "Science Fiction Adventure",
      "keywords": "saving the world san francisco uss enterprise-a time travel whale",
      "originalTitle": "Star Trek IV: The Voyage Home",
      "overview": "Fugitives of the Federation for their daring rescue of Spock from the doomed Genesis Planet, Admiral Kirk (William Shatner) and his crew begin their journey home to face justice for their actions. But as they near Earth, they find it at the mercy of a mysterious alien presence whose signals are slowly destroying the planet. In a desperate attempt to answer the call of the probe, Kirk and his crew race back to the late twentieth century. However they soon find the world they once knew to be more alien than anything they've encountered in the far reaches of the galaxy!",
      "popularity": 22.258428,
      "productionCompanies": "[{\"name\": \"Paramount Pictures\", \"id\": 4}]",
      "releaseDate": "1986-11-25",
      "title": "Star Trek IV: The Voyage Home"
    },
    {
      "director": "Gary Nelson",
      "genres": "Adventure Family Science Fiction Action",
      "keywords": "killer robot space marine ghost ship black hole",
      "originalTitle": "The Black Hole",
      "overview": "The explorer craft U.S.S. Palomino is returning to Earth after a fruitless 18-month search for extra-terrestrial life when the crew comes upon a supposedly lost ship, the magnificent U.S.S. Cygnus, hovering near a black hole. The ship is controlled by Dr. Hans Reinhardt and his monstrous robot companion, Maximillian. But the initial wonderment and awe the Palomino crew feel for the ship and its resistance to the power of the black hole turn to horror as they uncover Reinhardt's plans.",
      "popularity": 8.265317,
      "productionCompanies": "[{\"name\": \"Walt Disney Productions\", \"id\": 3166}]",
      "releaseDate": "1979-12-18",
      "title": "The Black Hole"
    },
    {
      "director": "J.J. Abrams",
      "genres": "Action Adventure Science Fiction",
      "keywords": "spacecraft friendship sequel futuristic space",
      "originalTitle": "Star Trek Into Darkness",
      "overview": "When the crew of the Enterprise is called back home, they find an unstoppable force of terror from within their own organization has detonated the fleet and everything it stands for, leaving our world in a state of crisis.  With a personal score to settle, Captain Kirk leads a manhunt to a war-zone world to capture a one man weapon of mass destruction. As our heroes are propelled into an epic chess game of life and death, love will be challenged, friendships will be torn apart, and sacrifices must be made for the only family Kirk has left: his crew.",
      "popularity": 78.291018,
      "productionCompanies": "[{\"name\": \"Paramount Pictures\", \"id\": 4}, {\"name\": \"Skydance Productions\", \"id\": 6277}, {\"name\": \"Bad Robot\", \"id\": 11461}, {\"name\": \"Kurtzman/Orci\", \"id\": 12536}]",
      "releaseDate": "2013-05-05",
      "title": "Star Trek Into Darkness"
    },
    {
      "director": "Paul W.S. Anderson",
      "genres": "Horror Science Fiction Mystery",
      "keywords": "space marine nudity nightmare hallucination cryogenics",
      "originalTitle": "Event Horizon",
      "overview": "In the year 2047 a group of astronauts are sent to investigate and salvage the long lost starship \"Event Horizon\". The ship disappeared mysteriously 7 years before on its maiden voyage and with its return comes even more mystery as the crew of the \"Lewis and Clark\" discover the real truth behind its disappearance and something even more terrifying.",
      "popularity": 29.787135,
      "productionCompanies": "[{\"name\": \"Paramount Pictures\", \"id\": 4}, {\"name\": \"Impact Pictures\", \"id\": 248}, {\"name\": \"Golar Productions\", \"id\": 2484}]",
      "releaseDate": "1997-08-15",
      "title": "Event Horizon"
    }
  ]
}

Essa rota permitirá que você receba recomendações personalizadas baseadas na descrição do filme que você forneceu, tornando sua experiência de escolha de filme mais fácil e divertida

Aproveite!

image

7
3 202
Artigo Heloisa Paiva · Nov. 6, 2024 5m read

Bem-vindo à terceira e última publicação de nossos artigos dedicados ao desenvolvimento de aplicações RAG baseadas em modelos LLM. Neste último artigo, veremos, com base em nosso pequeno projeto de exemplo, como podemos encontrar o contexto mais adequado para a pergunta que queremos enviar ao nosso modelo LLM e para isso utilizaremos a funcionalidade de busca vetorial incluída no IRIS.

Pesquisas vetoriais

0
0 108
Artigo Heloisa Paiva · Nov. 4, 2024 6m read

Continuamos com esta série de artigos sobre LLMs e aplicações RAG e neste artigo discutiremos a parte da caixa vermelha do seguinte diagrama:

No processo de criação de uma aplicação RAG, escolher um modelo LLM adequado às suas necessidades (treinado no assunto correspondente, custos, velocidade, etc.) é tão importante quanto ter um claro entendimento do contexto que você deseja fornecer. Vamos começar definindo o termo para ficarmos claros sobre o que entendemos por contexto.

O que é contexto?

0
0 309
Artigo Robert Cemper · Out. 19, 2024 4m read

Motivado pelo feedback pessoal de @Edilson Eberle Carvalho  e  uma excelente
apresentação de @Michael Braam relacionada com a Pesquisa Vetorial,
gostaria de partilhar a minha abordagem pessoal aos Vectores.

Quando comecei e encontrei vectores com 256, 384 e mais de 1200 dimensões - senti-me perdido.
No entanto, o meu exemplo Vector-inside-IRIS - uma simplificação da iris-vector-search - funcionou bem.

0
0 39
Artigo Heloisa Paiva · Out. 14, 2024 2m read

Em ObjectScript, você tem uma ampla coleção de funções que retornam algum valor tipicamente:

set variable = $somefunction(param1,param2, ...)

Não há nada de especial nisso.
Mas há um conjunto de funções que classifico como Funções de Lado Esquerdo
A especialidade delas é que você também pode usá-las à esquerda do operador igual como um alvo no comando SET:

set $somefunction(param1,param2, ...) = value

O motivo para levantar esse assunto é que com o IRIS 2024.1 há depois de muitos anos um "novo garoto nessa vizinhança"

$VECTOR()

0
0 38
InterSystems Oficial Danusa Calixto · Out. 10, 2024

Recentemente, disponibilizamos uma nova versão do InterSystems IRIS no Vector Search Early Access Program, apresentando um novo índice Approximate Nearest Neighbor baseado no algoritmo de indexação Hierarchical Navigable Small World (HNSW). Essa adição permite pesquisas altamente eficientes e aproximadas de vizinhos mais próximos em grandes conjuntos de dados vetoriais, melhorando drasticamente o desempenho e a escalabilidade da consulta.

0
0 54
Artigo Heloisa Paiva · Ago. 21, 2024 29m read

Um experimento sobre como usar a framework LangChain, Busca por Vetor IRIS e LLMs para gerar SQL compatível com IRIS de prompts de usuários.

Esse artigo foi baseado neste notebook. Você pode rodar com um ambiente pronto para uso com esta aplicação no OpenExchange.

Setup

Primeiro, precisamos instalar as livrarias necessárias:

!pip install --upgrade --quiet langchain langchain-openai langchain-iris pandas

Em seguida, importamos os módulos requeridos e definimos o ambiente:

import os
import datetime
import hashlib
from copy import deepcopy
from sqlalchemy import create_engine
import getpass
import pandas as pd
from langchain_core.prompts import PromptTemplate, ChatPromptTemplate
from langchain_core.example_selectors import SemanticSimilarityExampleSelector
from langchain_openai import OpenAIEmbeddings, ChatOpenAI
from langchain.docstore.document import Document
from langchain_community.document_loaders import DataFrameLoader
from langchain.text_splitter import CharacterTextSplitter
from langchain_core.output_parsers import StrOutputParser
from langchain.globals import set_llm_cache
from langchain.cache import SQLiteCache
from langchain_iris import IRISVector

Vamos usar SQLiteCache para manter as chamadas de LLM em cache:

# Cache for LLM calls
set_llm_cache(SQLiteCache(database_path=".langchain.db"))

Defina os parâmetros da conexão da base de dados IRIS:

# IRIS database connection parameters
os.environ["ISC_LOCAL_SQL_HOSTNAME"] = "localhost"
os.environ["ISC_LOCAL_SQL_PORT"] = "1972"
os.environ["ISC_LOCAL_SQL_NAMESPACE"] = "IRISAPP"
os.environ["ISC_LOCAL_SQL_USER"] = "_system"
os.environ["ISC_LOCAL_SQL_PWD"] = "SYS"

Se a chave da OpenAI API não está definida, peça ao usuário para fornecê-la:

if not "OPENAI_API_KEY" in os.environ:
    os.environ["OPENAI_API_KEY"] = getpass.getpass()

Crie a string de conxão para a base de dados IRIS:

# IRIS database connection string
args = {
    'hostname': os.getenv("ISC_LOCAL_SQL_HOSTNAME"), 
    'port': os.getenv("ISC_LOCAL_SQL_PORT"), 
    'namespace': os.getenv("ISC_LOCAL_SQL_NAMESPACE"), 
    'username': os.getenv("ISC_LOCAL_SQL_USER"), 
    'password': os.getenv("ISC_LOCAL_SQL_PWD")
}
iris_conn_str = f"iris://{args['username']}:{args['password']}@{args['hostname']}:{args['port']}/{args['namespace']}"

Estabeleça a conexão para a base de dados IRIS:

# Connection to IRIS database
engine = create_engine(iris_conn_str)
cnx = engine.connect().connection

Prepare um dicionário para guardar informações de contexto para o prompt do sistema:

# Dict for context information for system prompt
context = {}
context["top_k"] = 3

Criação de Prompt

Para transformar inputs de usuário em consultas SQL compatíveis com a base de dados IRIS, precisamos criar um prompt efetivo para o modelo de linguagem. Começamos com um prompt inicial que fornece instruções básicas para gerar queries SQL. O template é derivado de prompts default do LangChain's para MSSQL e customizado para a base de dados IRIS.

# Basic prompt template with IRIS database SQL instructions
iris_sql_template = """
Você é um expert em InterSystems IRIS. Dada uma questão como entrada, crie primeiro uma consulta com sintaxe correta para rodar e retorne a resposta para a questão de entrada.
A não ser que o usuário especifique na questão um número específico de exemplos a obter, pesquise por no máximo {top_k} resultados usando a cláusula TOP para o InterSystems IRIS. Você pode ordenar resultados para os dados mais informativos na base de dados.
Nunca pesquise todas as colunas de uma tabela. Você deve consultar apenas as colunas necessárias para responder a questão. Envolva cada nome de coluna em aspas simples para deontar que são identificadores delimitados.
Preste atenção para usar apenas nomes de colunas que você pode ver nas tabelas abaixo. Cuidado para não consultar colunas que não existem. Além disso, preste atenção em qual coluna está em qual tabela.
Atente-se em usar a função CAST(CURRENT_DATE as date) para buscar a data atual, se a questão envolve "hoje".
Use aspas duplas para delimitar identificadores de colunas.
Retorne apenas SQL puro; não aplique nenhum tipo de formatação.
"""

Esse prompt básico configura o modelo de linguagem (LLM) para funcionar como um expert em SQL com guia específico para a base de dados IRIS. Em seguida, fornecemos um prompt auxiliar com informação sobre a base de dados para evitar exageros.

# SQL template extension for including tables context information
tables_prompt_template = """
Only use the following tables:
{table_info}
"""

Para melhorar a acurácia das respostas LLM, usamos uma técnica chamada few-shot prompting. Isso envolve apresentar alguns exemplos para a LLM.

# SQL template extension for including few shots
prompt_sql_few_shots_template = """
Below are a number of examples of questions and their corresponding SQL queries.

{examples_value}
"""

Definimos o template para exemplos few-shot:

# Few shots prompt template
example_prompt_template = "User input: {input}\nSQL query: {query}"
example_prompt = PromptTemplate.from_template(example_prompt_template)

Construímos o prompt de usuário usando o template few-shot:

# User prompt template
user_prompt = "\n" + example_prompt.invoke({"input": "{input}", "query": ""}).to_string()

Finalmente, podemos compor todos os prompts para criar o prompt final:

# Complete prompt template
prompt = (
    ChatPromptTemplate.from_messages([("system", iris_sql_template)])
    + ChatPromptTemplate.from_messages([("system", tables_prompt_template)])
    + ChatPromptTemplate.from_messages([("system", prompt_sql_few_shots_template)])
    + ChatPromptTemplate.from_messages([("human", user_prompt)])
)
prompt

Esse prompt espera as variáveis examples_value, input, table_info, etop_k.

É assim que o prompt é estruturado:

ChatPromptTemplate(
    input_variables=['examples_value', 'input', 'table_info', 'top_k'], 
    messages=[
        SystemMessagePromptTemplate(
            prompt=PromptTemplate(
                input_variables=['top_k'], 
                template=iris_sql_template
            )
        ), 
        SystemMessagePromptTemplate(
            prompt=PromptTemplate(
                input_variables=['table_info'], 
                template=tables_prompt_template
            )
        ), 
        SystemMessagePromptTemplate(
            prompt=PromptTemplate(
                input_variables=['examples_value'], 
                template=prompt_sql_few_shots_template
            )
        ), 
        HumanMessagePromptTemplate(
            prompt=PromptTemplate(
                input_variables=['input'], 
                template=user_prompt
            )
        )
    ]
)

Para visualizar como o prompt será enviado a LLM, podemos usar valores no espaço reservado para as variáveis requeridas:

prompt_value = prompt.invoke({
    "top_k": "<top_k>",
    "table_info": "<table_info>",
    "examples_value": "<examples_value>",
    "input": "<input>"
})
print(prompt_value.to_string())
Sistema: 
Você é um expert em InterSystems IRIS. Dada uma questão como entrada, crie primeiro uma consulta com sintaxe correta para rodar e retorne a resposta para a questão de entrada.
A não ser que o usuário especifique na questão um número específico de exemplos a obter, pesquise por no máximo {top_k} resultados usando a cláusula TOP para o InterSystems IRIS. Você pode ordenar resultados para os dados mais informativos na base de dados.
Nunca pesquise todas as colunas de uma tabela. Você deve consultar apenas as colunas necessárias para responder a questão. Envolva cada nome de coluna em aspas simples para deontar que são identificadores delimitados.
Preste atenção para usar apenas nomes de colunas que você pode ver nas tabelas abaixo. Cuidado para não consultar colunas que não existem. Além disso, preste atenção em qual coluna está em qual tabela.
Atente-se em usar a função CAST(CURRENT_DATE as date) para buscar a data atual, se a questão envolve "hoje".
Use aspas duplas para delimitar identificadores de colunas.
Retorne apenas SQL puro; não aplique nenhum tipo de formatação.

Sistema: 
Use  apenas as tabelas a seguir:
<table_info>

Sistema: 
Abaixo, seguem alguns exemplos de questões e suas consultas SQL correspondentes.

<examples_value>

Humano: 
Input do usuário: <input>
Consulta SQL: 

Agora estamos prontos para enviar esse prompt para o LLM providenciando as variáveis necessárias. Vamos seguir para o próximo passo quando estiver pronto.

Fornecendo informações de tabela

Para criar consultas SQL precisas, precisamos fornecer ao modelo de linguagem (LLM) informações detalhadas sobre as tabelas das bases de dados. Sem essa informação, o LLM deve gerar consultas que parecem plausíveis mas são incorretas devido a exageros. Então, nosso primeiro passo é criar uma função que retorna definições de tabelas da base de dados IRIS.

Função para retornar definições de tabelas

A função a seguir consulta a variável INFORMATION_SCHEMA para buscar as definições de tabela para um schema (esquema) específico. Se uma tabela específica for fornecida, ela retorna a definição daquela tabela; caso contrário, retorna definições para todas as tabelas naquele esquema.

def get_table_definitions_array(cnx, schema, table=None):
    cursor = cnx.cursor()

    # Base query to get columns information
    query = """
    SELECT TABLE_SCHEMA, TABLE_NAME, COLUMN_NAME, DATA_TYPE, IS_NULLABLE, COLUMN_DEFAULT, PRIMARY_KEY, null EXTRA
    FROM INFORMATION_SCHEMA.COLUMNS
    WHERE TABLE_SCHEMA = %s
    """
    
    # Parameters for the query
    params = [schema]

    # Adding optional filters
    if table:
        query += " AND TABLE_NAME = %s"
        params.append(table)
    
    # Execute the query
    cursor.execute(query, params)

    # Fetch the results
    rows = cursor.fetchall()
    
    # Process the results to generate the table definition(s)
    table_definitions = {}
    for row in rows:
        table_schema, table_name, column_name, column_type, is_nullable, column_default, column_key, extra = row
        if table_name not in table_definitions:
            table_definitions[table_name] = []
        table_definitions[table_name].append({
            "column_name": column_name,
            "column_type": column_type,
            "is_nullable": is_nullable,
            "column_default": column_default,
            "column_key": column_key,
            "extra": extra
        })

    primary_keys = {}
    
    # Build the output string
    result = []
    for table_name, columns in table_definitions.items():
        table_def = f"CREATE TABLE {schema}.{table_name} (\n"
        column_definitions = []
        for column in columns:
            column_def = f"  {column['column_name']} {column['column_type']}"
            if column['is_nullable'] == "NO":
                column_def += " NOT NULL"
            if column['column_default'] is not None:
                column_def += f" DEFAULT {column['column_default']}"
            if column['extra']:
                column_def += f" {column['extra']}"
            column_definitions.append(column_def)
        if table_name in primary_keys:
            pk_def = f"  PRIMARY KEY ({', '.join(primary_keys[table_name])})"
            column_definitions.append(pk_def)
        table_def += ",\n".join(column_definitions)
        table_def += "\n);"
        result.append(table_def)

    return result

Retornar definições de tabela para um Esquema

Para esse exemplo, usamos o esquema Aviation (aviação), que está disponível aqui.

# Retrieve table definitions for the Aviation schema
tables = get_table_definitions_array(cnx, "Aviation")
print(tables)

Essa função retorna os predicados CREATE TABLE para todas as tabelas no esquema Aviation:

[
    'CREATE TABLE Aviation.Aircraft (\n  Event bigint NOT NULL,\n  ID varchar NOT NULL,\n  AccidentExplosion varchar,\n  AccidentFire varchar,\n  AirFrameHours varchar,\n  AirFrameHoursSince varchar,\n  AirFrameHoursSinceLastInspection varchar,\n  AircraftCategory varchar,\n  AircraftCertMaxGrossWeight integer,\n  AircraftHomeBuilt varchar,\n  AircraftKey integer NOT NULL,\n  AircraftManufacturer varchar,\n  AircraftModel varchar,\n  AircraftRegistrationClass varchar,\n  AircraftSerialNo varchar,\n  AircraftSeries varchar,\n  Damage varchar,\n  DepartureAirportId varchar,\n  DepartureCity varchar,\n  DepartureCountry varchar,\n  DepartureSameAsEvent varchar,\n  DepartureState varchar,\n  DepartureTime integer,\n  DepartureTimeZone varchar,\n  DestinationAirportId varchar,\n  DestinationCity varchar,\n  DestinationCountry varchar,\n  DestinationSameAsLocal varchar,\n  DestinationState varchar,\n  EngineCount integer,\n  EvacuationOccurred varchar,\n  EventId varchar NOT NULL,\n  FlightMedical varchar,\n  FlightMedicalType varchar,\n  FlightPhase integer,\n  FlightPlan varchar,\n  FlightPlanActivated varchar,\n  FlightSiteSeeing varchar,\n  FlightType varchar,\n  GearType varchar,\n  LastInspectionDate timestamp,\n  LastInspectionType varchar,\n  Missing varchar,\n  OperationDomestic varchar,\n  OperationScheduled varchar,\n  OperationType varchar,\n  OperatorCertificate varchar,\n  OperatorCertificateNum varchar,\n  OperatorCode varchar,\n  OperatorCountry varchar,\n  OperatorIndividual varchar,\n  OperatorName varchar,\n  OperatorState varchar,\n  Owner varchar,\n  OwnerCertified varchar,\n  OwnerCountry varchar,\n  OwnerState varchar,\n  RegistrationNumber varchar,\n  ReportedToICAO varchar,\n  SeatsCabinCrew integer,\n  SeatsFlightCrew integer,\n  SeatsPassengers integer,\n  SeatsTotal integer,\n  SecondPilot varchar,\n  childsub bigint NOT NULL DEFAULT $i(^Aviation.EventC("Aircraft"))\n);',
    'CREATE TABLE Aviation.Crew (\n  Aircraft varchar NOT NULL,\n  ID varchar NOT NULL,\n  Age integer,\n  AircraftKey integer NOT NULL,\n  Category varchar,\n  CrewNumber integer NOT NULL,\n  EventId varchar NOT NULL,\n  Injury varchar,\n  MedicalCertification varchar,\n  MedicalCertificationDate timestamp,\n  MedicalCertificationValid varchar,\n  Seat varchar,\n  SeatbeltUsed varchar,\n  Sex varchar,\n  ShoulderHarnessUsed varchar,\n  ToxicologyTestPerformed varchar,\n  childsub bigint NOT NULL DEFAULT $i(^Aviation.AircraftC("Crew"))\n);',
    'CREATE TABLE Aviation.Event (\n  ID bigint NOT NULL DEFAULT $i(^Aviation.EventD),\n  AirportDirection integer,\n  AirportDistance varchar,\n  AirportElevation integer,\n  AirportLocation varchar,\n  AirportName varchar,\n  Altimeter varchar,\n  EventDate timestamp,\n  EventId varchar NOT NULL,\n  EventTime integer,\n  FAADistrictOffice varchar,\n  InjuriesGroundFatal integer,\n  InjuriesGroundMinor integer,\n  InjuriesGroundSerious integer,\n  InjuriesHighest varchar,\n  InjuriesTotal integer,\n  InjuriesTotalFatal integer,\n  InjuriesTotalMinor integer,\n  InjuriesTotalNone integer,\n  InjuriesTotalSerious integer,\n  InvestigatingAgency varchar,\n  LightConditions varchar,\n  LocationCity varchar,\n  LocationCoordsLatitude double,\n  LocationCoordsLongitude double,\n  LocationCountry varchar,\n  LocationSiteZipCode varchar,\n  LocationState varchar,\n  MidAir varchar,\n  NTSBId varchar,\n  NarrativeCause varchar,\n  NarrativeFull varchar,\n  NarrativeSummary varchar,\n  OnGroundCollision varchar,\n  SkyConditionCeiling varchar,\n  SkyConditionCeilingHeight integer,\n  SkyConditionNonCeiling varchar,\n  SkyConditionNonCeilingHeight integer,\n  TimeZone varchar,\n  Type varchar,\n  Visibility varchar,\n  WeatherAirTemperature integer,\n  WeatherPrecipitation varchar,\n  WindDirection integer,\n  WindDirectionIndicator varchar,\n  WindGust integer,\n  WindGustIndicator varchar,\n  WindVelocity integer,\n  WindVelocityIndicator varchar\n);'
]

Com essas definições de tabela, podemos seguir para o próximo passo, que é integrá-las ao nosso prompt para o LLM. Isso assegura que o LLM tem informações precisas e compreensivas sobre o esquema da base de dados ao gerar consultas SQL.

Selecionando as tabelas mais relevantes

Ao trabalhar com bases de dados, especialmente as maiores, enviar a linguagem de definição de dados (Data Definition Language ou DDL) para todas as tabelas em um prompt pode ser impraticável. Ao passo que essa abordagem pode funcionar para bases de dados menores, as bases de dados reais frequentemente contém centenas ou milhares de tabelas, sendo ineficiente processá-las por completo.

No entanto, é improvável que um modelo de linguagem precise saber cada tabela numa base de dados para gerar consultas SQL efetivamente. Para endereçar esse desafio, podemos nivelar as capacidades da procura semântica para selecionar apenas tabelas relevantes baseadas na consulta do usuário.

Abordagem

Nós podemos conseguir isso usando a procura semântica com a Procura de Vetor IRIS. Note que este método é mais efetivo se os seus identificadores de elementos SQL (como tabelas, campos e chaves) têm nomes significativos. Se seus identificadores forem códigos abstratos, consiere usar um dicionário de dados no lugar.

Passos

  1. Retornar informação de tabela

Primeiro, vamos extrair as definições de tabelas para um DataFrame pandas:

# Retrieve table definitions into a pandas DataFrame
table_def = get_table_definitions_array(cnx=cnx, schema='Aviation')
table_df = pd.DataFrame(data=table_def, columns=["col_def"])
table_df["id"] = table_df.index + 1
table_df

O DataFrame (table_df) deve se parecer com algo assim:

col_defid
0CREATE TABLE Aviation.Aircraft (\n Event bigi...1
1CREATE TABLE Aviation.Crew (\n Aircraft varch...2
2CREATE TABLE Aviation.Event (\n ID bigint NOT...3
  1. Separar as definições em documentos:

Em seguida, divida as definições de tabelas em documentos LangChain. Esse passo é crucial para lidar com grandes conjuntos de texto e extrair textos embutidos:

loader = DataFrameLoader(table_df, page_content_column="col_def")
documents = loader.load()
text_splitter = CharacterTextSplitter(chunk_size=400, chunk_overlap=20, separator="\n")
tables_docs = text_splitter.split_documents(documents)
tables_docs

A lista resultante tables_docs contém documentos divididos com metadados, como o seguinte:

[Document(metadata={'id': 1}, page_content='CREATE TABLE Aviation.Aircraft (\n  Event bigint NOT NULL,\n  ID varchar NOT NULL,\n  ...'),
 Document(metadata={'id': 2}, page_content='CREATE TABLE Aviation.Crew (\n  Aircraft varchar NOT NULL,\n  ID varchar NOT NULL,\n  ...'),
 Document(metadata={'id': 3}, page_content='CREATE TABLE Aviation.Event (\n  ID bigint NOT NULL DEFAULT $i(^Aviation.EventD),\n  ...')]
  1. Extrair embutidos e guardar em IRIS

Agora, use a classe IRISVector do langchain-iris para extrair vetores embutidos e guardá-los:

tables_vector_store = IRISVector.from_documents(
    embedding=OpenAIEmbeddings(), 
    documents=tables_docs,
    connection_string=iris_conn_str,
    collection_name="sql_tables",
    pre_delete_collection=True
)

Nota: A bandeira pre_delete_collection é definida como True (verdadeiro) para propósitos de demonstração, para assegurar uma coleção nova em cada rodada de teste. Em um ambinte produtivo, essa bandeira geralmente deve ser definida como False (falso).

  1. Achar documentos relevantes

Com tabela de embutidos guardada, você agora pode consultar tabelas relevantes baseadas no input do usuário:

input_query = "List the first 2 manufacturers"
relevant_tables_docs = tables_vector_store.similarity_search(input_query, k=3)
relevant_tables_docs

Por exemplo, consultar por manufaturas pode retornar:

[Document(metadata={'id': 1}, page_content='GearType varchar,\n  LastInspectionDate timestamp,\n  ...'),
 Document(metadata={'id': 1}, page_content='AircraftModel varchar,\n  AircraftRegistrationClass varchar,\n  ...'),
 Document(metadata={'id': 3}, page_content='LocationSiteZipCode varchar,\n  LocationState varchar,\n  ...')]

Para os metadados, você pode ver que apenas o ID 1 da tabela (Aviation.Aircraft) é relevante, que linha com a consulta.

  1. Lidando com casos extremos

Apesar desta abordagem ser geralmente efetiva, pode não ser sempre perfeita. Por exemplo, consultar por áreas de queda pode retornar tabelas menos relevantes:

input_query = "List the top 10 most crash sites"
relevant_tables_docs = tables_vector_store.similarity_search(input_query, k=3)
relevant_tables_docs

Os resultados podem incluir:

[Document(metadata={'id': 3}, page_content='LocationSiteZipCode varchar,\n  LocationState varchar,\n  ...'),
 Document(metadata={'id': 3}, page_content='InjuriesGroundSerious integer,\n  InjuriesHighest varchar,\n  ...'),
 Document(metadata={'id': 1}, page_content='CREATE TABLE Aviation.Aircraft (\n  Event bigint NOT NULL,\n  ID varchar NOT NULL,\n  ...')]

Apesar de retornar a tabela correta Aviation.Event duas vezes, a tabela Aviation.Aircraft também pode aparecer, o que pode ser melhorado com filtros adicionais ou limitações. Isso está além do escopo deste exemplo e vai ser deixado para implementações futuras.

  1. Defina uma função para retornar tabelas relevantes

Para automatizar este processo, defina uma função para filtrar e retornar as tabelas relevantes baseado no input do usuário:

def get_relevant_tables(user_input, tables_vector_store, table_df):
    relevant_tables_docs = tables_vector_store.similarity_search(user_input)
    relevant_tables_docs_indices = [x.metadata["id"] for x in relevant_tables_docs]
    indices = table_df["id"].isin(relevant_tables_docs_indices)
    relevant_tables_array = [x for x in table_df[indices]["col_def"]]
    return relevant_tables_array

Essa função vai ajudar em retornar de maneira eficiente apenas as tabelas relevantes a enviar ao LLM, reduzindo o tamanho do prompt e melhorando a performance da consulta num geral.

Selecionando os exemplos mais relevantes (Few-Shot Prompting)

Ao trabalhar com modelos de linguagem (LLMs), fornecer exemplos relevantes ajuda a assegurar respostas precisas e contextualmente apropriadas. Esses exemplos, referidos como exemplos "few-shot", guiam o LLM para entender a estrutura e contexto das consultas que deve manusear. No nosso caso, precisamos popular a variável examples_value com um conjunto diverso de consultas SQL que cobrem um espectro vasto de sinitaxe IRIS SQL e as tabelas disponíveis na base de dados. Isso ajuda a prevenir que o LLM gere consultas incorretas ou irrelevantes.

Definindo Consultas de Exemplo

Abaixo, uma lista de queries de exemplo desenhadas para ilustrar várias operações SQL:

examples = [
    {"input": "List all aircrafts.", "query": "SELECT * FROM Aviation.Aircraft"},
    {"input": "Find all incidents for the aircraft with ID 'N12345'.", "query": "SELECT * FROM Aviation.Event WHERE EventId IN (SELECT EventId FROM Aviation.Aircraft WHERE ID = 'N12345')"},
    {"input": "List all incidents in the 'Commercial' operation type.", "query": "SELECT * FROM Aviation.Event WHERE EventId IN (SELECT EventId FROM Aviation.Aircraft WHERE OperationType = 'Commercial')"},
    {"input": "Ache o número total de incidentes.", "query": "SELECT COUNT(*) FROM Aviation.Event"},
    {"input": "Liste todos os incidentes que ocorreram no 'Canadá'.", "query": "SELECT * FROM Aviation.Event WHERE LocationCountry = 'Canada'"},
    {"input": "Quantos incidentes estão associados com a aeronave com AircraftKey 5?", "query": "SELECT COUNT(*) FROM Aviation.Aircraft WHERE AircraftKey = 5"},
    {"input": "Ache o número total de diferentes aeronaves envolvidas em incidentes.", "query": "SELECT COUNT(DISTINCT AircraftKey) FROM Aviation.Aircraft"},
    {"input": "Liste todos os incidentes que ocorreram após 5 PM.", "query": "SELECT * FROM Aviation.Event WHERE EventTime > 1700"},
    {"input": "Quem são os top 5 operadores por número de incidentes?", "query": "SELECT TOP 5 OperatorName, COUNT(*) AS IncidentCount FROM Aviation.Aircraft GROUP BY OperatorName ORDER BY IncidentCount DESC"},
    {"input": "Quais incidentes ocorreram no ano 2020?", "query": "SELECT * FROM Aviation.Event WHERE YEAR(EventDate) = '2020'"},
    {"input": "Qual foi o mês com mais incidentes no ano 2020?", "query": "SELECT TOP 1 MONTH(EventDate) EventMonth, COUNT(*) EventCount FROM Aviation.Event WHERE YEAR(EventDate) = '2020' GROUP BY MONTH(EventDate) ORDER BY EventCount DESC"},
    {"input": "Quantos membros de tripulação foram envolvidos em incidentes?", "query": "SELECT COUNT(*) FROM Aviation.Crew"},
    {"input": "Liste todos os incidentes com informações detalhadas da aeronave para os incidentes que ocorreram no ano 2012.", "query": "SELECT e.EventId, e.EventDate, a.AircraftManufacturer, a.AircraftModel, a.AircraftCategory FROM Aviation.Event e JOIN Aviation.Aircraft a ON e.EventId = a.EventId WHERE Year(e.EventDate) = 2012"},
    {"input": "Ache todos os incidentes onde houve mais de 5 feridos e inclua a fabricante da aeronave e modelo.", "query": "SELECT e.EventId, e.InjuriesTotal, a.AircraftManufacturer, a.AircraftModel FROM Aviation.Event e JOIN Aviation.Aircraft a ON e.EventId = a.EventId WHERE e.InjuriesTotal > 5"},
    {"input": "Liste todos os membros da tripulação envolvidos em incidentes com machucados sérios, junto da da data de incidente e localização.", "query": "SELECT c.CrewNumber AS 'Crew Number', c.Age, c.Sex AS Gender, e.EventDate AS 'Event Date', e.LocationCity AS 'Location City', e.LocationState AS 'Location State' FROM Aviation.Crew c JOIN Aviation.Event e ON c.EventId = e.EventId WHERE c.Injury = 'Serious'"}
]

[ Nota do tradutor: as frases foram traduzidas para fins de compreensão, mas os as informações de colunas nas frases deveriam idealmente ser deixadas em inglês para o interpretador melhor associar com as colunas na tabela, que estão em inglês. Segue um breve glossário: Aviation.Aircraft = Aviação.Aeronave key = chave month = mês count = contagem OpertationType = tipo de operação OperatorName = nome do operador LocationCountry = país de localização State = estado City = cidade Crew = Tripulação Injury = ferimento ]

Selecionando Exemplos Relevantes

Dada a lista de exemplos que vai sempre expandir, não é uma boa ideia fornecer todas elas ao LLM. Ao invés disso, vamos usar a Busca Vetorial IRIS com a classe SemanticSimilarityExampleSelector to identify the most relevant examples based on user prompts.

Defina o seletor de exemplo:

example_selector = SemanticSimilarityExampleSelector.from_examples(
    examples,
    OpenAIEmbeddings(),
    IRISVector,
    k=5,
    input_keys=["input"],
    connection_string=iris_conn_str,
    collection_name="sql_samples",
    pre_delete_collection=True
)

Nota: A bandeira pre_delete_collection é usada aqui para propósitos de demonstração para assegura uma coleção nova em cada rodada de teste. Em um ambiente produtivo, essa bandeira deve ser definida como False para evitar deleções desnecessárias.

Consulte o Seletor:

Para buscar os exemplos mais relevantes para uma dada entrada, use o seletor como se segue:

input_query = "Busque todos os eventos em 2010 informando o Event Id e date, location city e state, aircraft manufacturer e model."
relevant_examples = example_selector.select_examples({"input": input_query})

Os resultados devem parecer como algo assim:

[{'input': 'Liste todos os incidents com informações detalhadas sobre a Aircraft para os incidentes que ocorreram no year 2012.', 'query': 'SELECT e.EventId, e.EventDate, a.AircraftManufacturer, a.AircraftModel, a.AircraftCategory FROM Aviation.Event e JOIN Aviation.Aircraft a ON e.EventId = a.EventId WHERE Year(e.EventDate) = 2012'},
 {'input': "Busque todos os incidents para a Aircraft de ID 'N12345'.", 'query': "SELECT * FROM Aviation.Event WHERE EventId IN (SELECT EventId FROM Aviation.Aircraft WHERE ID = 'N12345')"},
 {'input': 'Ache todos os incidents onde houve mais de 5 injuries e inclua o aircraft manufacturer e model.', 'query': 'SELECT e.EventId, e.InjuriesTotal, a.AircraftManufacturer, a.AircraftModel FROM Aviation.Event e JOIN Aviation.Aircraft a ON e.EventId = a.EventId WHERE e.InjuriesTotal > 5'},
 {'input': 'Liste todas as aircrafts.', 'query': 'SELECT * FROM Aviation.Aircraft'},
 {'input': 'Ache o número total de aircrafts distintas envolvidas em incidents.', 'query': 'SELECT COUNT(DISTINCT AircraftKey) FROM Aviation.Aircraft'}]

Se você especificamente precisa de exemplos relacionados a quantidades, você pode procurar o seletor conforme:

input_query = "Qual foi o número de incidentes envolvendo a aircraft Boeing."
quantity_examples = example_selector.select_examples({"input": input_query})

A saída será:

[{'input': 'Quantos incidents estão associados à aircraft de AircraftKey 5?', 'query': 'SELECT COUNT(*) FROM Aviation.Aircraft WHERE AircraftKey = 5'},
 {'input': 'Busque o número total de aircrafts distintas envolvidas em incidents.', 'query': 'SELECT COUNT(DISTINCT AircraftKey) FROM Aviation.Aircraft'},
 {'input': 'Quantos membros de tripulação foram envolvidos em incidents?', 'query': 'SELECT COUNT(*) FROM Aviation.Crew'},
 {'input': 'Ache todos os incidents onde houve mais de 5 ferimentos e inclua a aircraft manufacturer e model.', 'query': 'SELECT e.EventId, e.InjuriesTotal, a.AircraftManufacturer, a.AircraftModel FROM Aviation.Event e JOIN Aviation.Aircraft a ON e.EventId = a.EventId WHERE e.InjuriesTotal > 5'},
 {'input': 'Liste todos os incidents com informação detalhada sobre as aircrafts para incidents que ocorreram no ano 2012.', 'query': 'SELECT e.EventId, e.EventDate, a.AircraftManufacturer, a.AircraftModel, a.AircraftCategory FROM Aviation.Event e JOIN Aviation.Aircraft a ON e.EventId = a.EventId WHERE Year(e.EventDate) = 2012'}]

A saída inclui exemplos que especificamente buscam contagens e quantidades.

Considerações futuras

Apesar do SemanticSimilarityExampleSelector ser poderoso, é importante nota que nem todos os exemplos serão perfeitos. Melhorias futuras podem incluir adição de filtros e limites para excluir resultados menos relevantes, assegurando que apenas os exemplos mais apropriados sejam fornecidos ao LLM.

Teste de precisão

Para acessar a performance do prompt e da geração de consultas SQL, precisamos definir e rodar uma série de testes. O objetivo é avaliar se a LLM gera de maneira ótima as consultas SQL baseadas em inputs de usuários e sem o uso dos few shots baseados em exemplos.

Função para gerar consultas SQL

Nós começamos definindo uma função que usa LLM para gerar consultas SQL baseadas no contexto providenciado, prompt, entrada do usuários e outros parâmetros:

def get_sql_from_text(context, prompt, user_input, use_few_shots, tables_vector_store, table_df, example_selector=None, example_prompt=None):
    relevant_tables = get_relevant_tables(user_input, tables_vector_store, table_df)
    context["table_info"] = "\n\n".join(relevant_tables)

    examples = example_selector.select_examples({"input": user_input}) if example_selector else []
    context["examples_value"] = "\n\n".join([
        example_prompt.invoke(x).to_string() for x in examples
    ])
    
    model = ChatOpenAI(model="gpt-3.5-turbo", temperature=0)
    output_parser = StrOutputParser()
    chain_model = prompt | model | output_parser
    
    response = chain_model.invoke({
        "top_k": context["top_k"],
        "table_info": context["table_info"],
        "examples_value": context["examples_value"],
        "input": user_input
    })
    return response

Execute o Prompt

Teste o prompt com e sem exemplos:

# Prompt execution **with** few shots
input = "Busque todos os eventos em 2010 informando o Event Id e date, location city e state, aircraft manufacturer e model."
response_with_few_shots = get_sql_from_text(
    context, 
    prompt, 
    user_input=input, 
    use_few_shots=True, 
    tables_vector_store=tables_vector_store, 
    table_df=table_df,
    example_selector=example_selector, 
    example_prompt=example_prompt,
)
print(response_with_few_shots)
SELECT e.EventId, e.EventDate, e.LocationCity, e.LocationState, a.AircraftManufacturer, a.AircraftModel
FROM Aviation.Event e
JOIN Aviation.Aircraft a ON e.EventId = a.EventId
WHERE Year(e.EventDate) = 2010
# Prompt execution **without** few shots
input = "Busque todos os eventos em 2010 informando o Event Id e date, location city e state, aircraft manufacturer e model."
response_with_no_few_shots = get_sql_from_text(
    context, 
    prompt, 
    user_input=input, 
    use_few_shots=False, 
    tables_vector_store=tables_vector_store, 
    table_df=table_df,
)
print(response_with_no_few_shots)
SELECT TOP 3 "EventId", "EventDate", "LocationCity", "LocationState", "AircraftManufacturer", "AircraftModel"
FROM Aviation.Event e
JOIN Aviation.Aircraft a ON e.ID = a.Event
WHERE e.EventDate >= '2010-01-01' AND e.EventDate < '2011-01-01'
Utility Functions for Testing

Para testar as queries geradas por SQL, definimos algumas funções úteis:

def execute_sql_query(cnx, query):
    try:
        cursor = cnx.cursor()
        cursor.execute(query)
        rows = cursor.fetchall()
        return rows
    except:
        print('Error running query:')
        print(query)
        print('-'*80)
    return None

def sql_result_equals(cnx, query, expected):
    rows = execute_sql_query(cnx, query)
    result = [set(row._asdict().values()) for row in rows or []]
    if result != expected and rows is not None:
        print('Result not as expected for query:')
        print(query)
        print('-'*80)
    return result == expected
# SQL test for prompt **with** few shots
print("SQL is OK" if not execute_sql_query(cnx, response_with_few_shots) is None else "SQL is not OK")
    SQL is OK
# SQL test for prompt **without** few shots
print("SQL is OK" if not execute_sql_query(cnx, response_with_no_few_shots) is None else "SQL is not OK")
    error on running query: 
    SELECT TOP 3 "EventId", "EventDate", "LocationCity", "LocationState", "AircraftManufacturer", "AircraftModel"
    FROM Aviation.Event e
    JOIN Aviation.Aircraft a ON e.ID = a.Event
    WHERE e.EventDate >= '2010-01-01' AND e.EventDate < '2011-01-01'
    --------------------------------------------------------------------------------
    SQL is not OK

Defina e Execute Testes

Defina um conjunto de casos de teste e rode eles:

tests = [{
    "input": "Quais são os 3 anos com mais eventos gravados?",
    "expected": [{128, 2003}, {122, 2007}, {117, 2005}]
},{
    "input": "Quantos incidentes envolveram a aircraft Boeing.",
    "expected": [{5}]
},{
    "input": "Quantos incidentes resultaram em fatalidades.",
    "expected": [{237}]
},{
    "input": "Liste o event Id e date e, crew number, age e gender para incidents que ocorreram em 2013.",
    "expected": [{1, datetime.datetime(2013, 3, 4, 11, 6), '20130305X71252', 59, 'M'},
                 {1, datetime.datetime(2013, 1, 1, 15, 0), '20130101X94035', 32, 'M'},
                 {2, datetime.datetime(2013, 1, 1, 15, 0), '20130101X94035', 35, 'M'},
                 {1, datetime.datetime(2013, 1, 12, 15, 0), '20130113X42535', 25, 'M'},
                 {2, datetime.datetime(2013, 1, 12, 15, 0), '20130113X42535', 34, 'M'},
                 {1, datetime.datetime(2013, 2, 1, 15, 0), '20130203X53401', 29, 'M'},
                 {1, datetime.datetime(2013, 2, 15, 15, 0), '20130218X70747', 27, 'M'},
                 {1, datetime.datetime(2013, 3, 2, 15, 0), '20130303X21011', 49, 'M'},
                 {1, datetime.datetime(2013, 3, 23, 13, 52), '20130326X85150', 'M', None}]
},{
    "input": "Ache o total de incidents ocorridos em United States.",
    "expected": [{1178}]
},{
    "input": "Liste todos as coordenadas de latitude e longitude de incidentes que resultaram em mais de 5 feridos em 2010.",
    "expected": [{-78.76833333333333, 43.25277777777778}]
},{
    "input": "Busque todos os incidentes em 2010 informando o Event Id e date, location city e state, aircraft manufacturer e model.",
    "expected": [
        {datetime.datetime(2010, 5, 20, 13, 43), '20100520X60222', 'CIRRUS DESIGN CORP', 'Farmingdale', 'New York', 'SR22'},
        {datetime.datetime(2010, 4, 11, 15, 0), '20100411X73253', 'CZECH AIRCRAFT WORKS SPOL SRO', 'Millbrook', 'New York', 'SPORTCRUISER'},
        {'108', datetime.datetime(2010, 1, 9, 12, 55), '20100111X41106', 'Bayport', 'New York', 'STINSON'},
        {datetime.datetime(2010, 8, 1, 14, 20), '20100801X85218', 'A185F', 'CESSNA', 'New York', 'Newfane'}
    ]
}]

Avaliação de precisão

Rode os testes e calcule a precisão:

def execute_tests(cnx, context, prompt, use_few_shots, tables_vector_store, table_df, example_selector, example_prompt):
    tests_generated_sql = [(x, get_sql_from_text(
            context, 
            prompt, 
            user_input=x['input'], 
            use_few_shots=use_few_shots, 
            tables_vector_store=tables_vector_store, 
            table_df=table_df,
            example_selector=example_selector if use_few_shots else None, 
            example_prompt=example_prompt if use_few_shots else None,
        )) for x in deepcopy(tests)]
    
    tests_sql_executions = [(x[0], sql_result_equals(cnx, x[1], x[0]['expected'])) 
                            for x in tests_generated_sql]
    
    accuracy = sum(1 for i in tests_sql_executions if i[1] == True) / len(tests_sql_executions)
    print(f'Accuracy: {accuracy}')
    print('-'*80)

Resultados

# Testes de precisão para prompts executados **sem** few shots
use_few_shots = False
execute_tests(
    cnx,
    context, 
    prompt, 
    use_few_shots, 
    tables_vector_store, 
    table_df, 
    example_selector, 
    example_prompt
)
    error on running query: 
    SELECT "EventDate", COUNT("EventId") as "TotalEvents"
    FROM Aviation.Event
    GROUP BY "EventDate"
    ORDER BY "TotalEvents" DESC
    TOP 3;
    --------------------------------------------------------------------------------
    error on running query: 
    SELECT "EventId", "EventDate", "C"."CrewNumber", "C"."Age", "C"."Sex"
    FROM "Aviation.Event" AS "E"
    JOIN "Aviation.Crew" AS "C" ON "E"."ID" = "C"."EventId"
    WHERE "E"."EventDate" >= '2013-01-01' AND "E"."EventDate" < '2014-01-01'
    --------------------------------------------------------------------------------
    result not expected for query: 
    SELECT TOP 3 "e"."EventId", "e"."EventDate", "e"."LocationCity", "e"."LocationState", "a"."AircraftManufacturer", "a"."AircraftModel"
    FROM "Aviation"."Event" AS "e"
    JOIN "Aviation"."Aircraft" AS "a" ON "e"."ID" = "a"."Event"
    WHERE "e"."EventDate" >= '2010-01-01' AND "e"."EventDate" < '2011-01-01'
    --------------------------------------------------------------------------------
    accuracy: 0.5714285714285714
    --------------------------------------------------------------------------------
# Testes de precisão para prompts executados **com** few shots
use_few_shots = True
execute_tests(
    cnx,
    context, 
    prompt, 
    use_few_shots, 
    tables_vector_store, 
    table_df, 
    example_selector, 
    example_prompt
)
    error on running query: 
    SELECT e.EventId, e.EventDate, e.LocationCity, e.LocationState, a.AircraftManufacturer, a.AircraftModel
    FROM Aviation.Event e
    JOIN Aviation.Aircraft a ON e.EventId = a.EventId
    WHERE Year(e.EventDate) = 2010 TOP 3
    --------------------------------------------------------------------------------
    accuracy: 0.8571428571428571
    --------------------------------------------------------------------------------

Conclusão

A acurácia das consultas SQL geradas com exemplos (few shots) é aproximadamente 49% maior se comparada àquelas geradas sem exemplos (85% vs. 57%).

References

0
0 63
Artigo Heloisa Paiva · Jul. 29, 2024 4m read

Com a introdução dos tipos de dados vetoriais e da funcionalidade de Vector Search em IRIS, se abre todo um mundo de possibilidades para o desenvolvimento de aplicações para nós, e um exemplo delas é a que vi recentemente publicada num concurso do Conselho de Saúde de Valencia, onde solicitavam uma ferramenta para ajudar na codificação CID-10 utilizando modelos de IA.

Como poderíamos implementar uma aplicação similar à solicitada? Vejamos o que seria necessário:

0
0 53
Artigo Heloisa Paiva · Jun. 11, 2024 3m read

Traduzido do Concurso de Artigos da Comunidade Espanhola 

Seguindo o último concurso de programação no OEX (Open EXchange) eu tive algumas observações surpreendentes.
Havia aplicações quase exclusivas baseadas numa combinação de IA (Inteligência Artificial) com módulos Python "pré-cozidas".
Porém, indo mais a fundo, todos os exemplos usaram os mesmos fatores técnicos do IRIS.

Considerando o ponto de vista do IRIS, foi praticamente a mesma coisa seja buscando por textos, ou imagens, ou outro tipo de padrão. Acabou em métodos quase intercambiáveis.

0
0 41
Artigo Heloisa Paiva · Jun. 7, 2024 7m read

A ideia

Já estamos em 2024, a versão IRIS 2024.1 acabou de sair e estamos todos falando disso aqui. Já temos muitos tutoriais sobre busca vetorial e aplicações de chats de inteligência artificial. Hoje quero propor algo diferente. Quero apresentar uma ideia e explorar todos os seus limites e, ao longo do texto, vou levantar alguns questionamento sobre a capacidade da ferramentas utilizadas para que possamos compreender não só os resultados de as novas funcionalidades, mas também como a máquina as processa.

0
0 56
Artigo Heloisa Paiva · Maio 27, 2024 4m read

No artigo anterior, vimos detalhes a respeito dos conectores, que permitem que o usuário carregue o arquivo, o converta para incorporações e armazene na IRIS DB. Nesse artigo, vamos explorar opções diferentes de recuperações que o Studio IRIS AI oferece: Semantic Search (pesquisa semântica), Chat (conversa), Recommender (recomendação) e Similarity (similaridade).

Novas atualizações  ⛴️ 

0
0 89
Anúncio Heloisa Paiva · Maio 25, 2024

Olá Comunidade,

Aqui vai um simples passo a passo sobre as capacidades da plataforma  Studio IRIS AI. Ele cobre um fluxo completo de carregar dados no IRIS DB como incorporações de vetor e recuperação de informações usando 4 canais diferentes (pesquisa, conversa, recomendação e similaridade). No último lançamento, adicionei suporte para docker para instalações locais e uma versão ao vivo para explorar.

0
0 78
Artigo Heloisa Paiva · Maio 24, 2024 7m read

No artigo anterior, vimos diferentes módulos do Studio IRIS AI e como ele poderia ajudar a explorar as capacidades da GenAI além do IRIS DB perfeitamente, mesmo para alguém não técnico. Nesse artigo, vamos mergulhar a fundo pelo módulo "Connectors", o que permite que os usuários carreguem dados desde uma fonte local ou cloud (AWS S3, Airtable, Azure Blob) no IRSI DB como vetores incorporados, ao configurar também definições de incorporação como modelo e dimensões.

Novas Atualizações ⛴️ 

0
0 78
Artigo Heloisa Paiva · Maio 24, 2024 6m read

 

Problema

Você se identifica com isso: a capacidade e impacto da tecnologia que é realmente descoberta quando empacotada da maneira correta para seu público alvo? O melhor exemplo seria como a Generative AI deslanchou quando o ChatGPT veio ao público para fácil acesso e não como as capacidades Transformers/RAG's (Retrieval-Augmented Generation - Geração Aumentada de Recuperação) foram identificadas. Pelo menos uma usabilidade muito maior surgiu, quando a audiência foi incentivada para explorar as possibilidades.

Motivação

0
0 87