New post

Find

InterSystems Official
· Feb 11

InterSystems Language Server 2.7 最新情報

開発者コミュニティのみなさま、2025年もよろしくお願いします!今年も素晴らしい製品やニュースをみなさまにお届けいたします。本日は VS Code の InterSystems Language Server 拡張機能の最新バージョンをご紹介します。Language Server 拡張機能の多くは、ObjectScript 拡張機能を通じてご提供することが多いです。そのため、コード補完機能やホバー機能といった、2024年に追加された Language Server 拡張機能の新機能には、なかなか気づきにくいかもしれません。ぜひ Language Server 変更履歴 で、見逃していたかもしれない新機能がないかご確認ください。最新バージョン2.7.0では、Windows ARMプラットフォームがサポートされたので、Surface Pro 11 (私はこの記事をウキウキしながら書いています) のようなデバイスをお持ちの方は、お使いのマシンで素晴らしい ObjectScript 開発を体験いただけます。Language Server 拡張機能をお試しいただき、何かありましたらぜひコメントをお寄せくださいませ。お待ちしております。

Discussion (0)0
Log in or sign up to continue
Article
· Feb 11 2m read

第二十一章 P 开头的术语

第二十一章 P 开头的术语

主持久超类 (primary persistent superclass)

对象(Objects)

一个类的主要持久超类决定了该类的持久行为。默认情况下,主要持久超类是超类列表中最左侧的持久超类。通常,与相同主要持久超类相关联的类的所有数据一起存储。

主卷 (primary volume)

系统

卷集中的第一个卷或唯一卷。

主设备 (principal device)

系统

与进程相关联的输入/输出设备,通常是终端或计算机键盘和显示器。对于后台进程,你可以在 JOB 命令中分配主设备,或者在系统配置编辑器中将其设置为父进程的主设备。如果不以这些方式设置设备,则后台进程的默认设备是空设备(null device)。

Discussion (0)1
Log in or sign up to continue
Article
· Feb 11 8m read

Utilizando o Gateway SQL com Python, Vector Search e Interoperabilidade no InterSystems Iris - Parte 3 – REST e Interoperabilidade

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

Parte 3 – REST e Interoperabilidade

Agora que finalizamos a configuração do Gateway SQL e conseguimos acessar os dados do banco externo via python, e montamos nossa base vetorizada, podemos realizar algumas consultas. Para isso nessa parte do artigo vamos utilizar uma aplicação que desenvolvida com CSP, HTML e Javascript que acessará uma integração no Iris, que então realiza a pesquisa por similaridade dos dados, faz o envio para a LLM e por fim devolve o SQL gerado. A página CSP chama uma API no Iris que recebe os dados a serem utilizados na consulta, chamando a integração. Para mais informações sobre REST nop Iris veja a documentação disponível em https://docs.intersystems.com/irislatest/csp/docbook/DocBook.UI.Page.cls...

A seguir o código da API REST criada:

Class Rest.Vector Extends %CSP.REST
{

XData UrlMap
{
<Routes>
        <Route Url="/buscar" Method="GET" Call="Buscar"  Cors="true"/>
    </Routes>
}

ClassMethod Buscar() As %Status
{
    set arg1 = %request.Get("arg1")
    set sessionID = %request.Get("sessionID")
    Set saida = {}
    Set obj=##Class(ws.rag.msg.Request).%New()
    Set obj.question=arg1
    Set obj.sessionId=sessionID
    Set tSC=##Class(Ens.Director).CreateBusinessService("ws.rag.bs.Service",.tService)
    If tSC
    {
                  Set resp=tService.entrada(obj)
    } Else {
                  Set resp=##Class(ws.rag.msg.Response).%New()
                  Set resp.resposta=$SYSTEM.Status.GetErrorText(tSC)
    }
    Set saida = {}
    Set saida.resposta=resp.resposta
    Set saida.sessionId=sessionID // Devolve o SessionId que chegou
    //
    Write saida.%ToJSON()
    Quit $$$OK
}

}

Uma vez criado o código da API REST precisamos criar a configuração da aplicação no Portal de Administração->Administração do Sistema->Segurança->Aplicações Web:

Na aplicação CSP, em Javascript, temos então a chamada da API:

...

async function chamaAPI(url, sessionID)

    var div = document.getElementById('loader');
    div.style.opacity=1;
    fetch(url)
         .then(response => {
               if (!response.ok) {
                     throw new Error('Erro na resposta da API');
               }
              return response.json();
         })
        .then(data => {
               incluiDIVRobot(data.resposta, data.sessionID);
        })
       .catch(error => {
               incluiDIVRobot('Erro na chamada da API:: ' + error, sessionID);
       });
 }

//

 const url = 'http://' + 'localhost' + '/api/vector/buscar?arg1=' + texto + '&sessionID=' + sessionID;
 chamaAPI(url, sessionID);

...

A aplicação CSP então recebe como entrada a solicitação do usuário (por exemplo: “qual a menor temperatura registrada?”) e chama a API REST.

 

A API REST por sua vez chama uma integração no Iris composta de Service, Process e Operation. Na camada de Operation temos a chamada a LLM, que é feita por um método em python de uma classe. Vendo o trace da integração podemos verificar o processo todo ocorrendo.

Para mais informações sobre o uso de produções no Iris veja a documentação disponível em https://docs.intersystems.com/irislatest/csp/docbook/DocBook.UI.Page.cls...

Abaixo os códigos utilizados nas camadas de BS, BP e BO:

A seguir o código do BS (Service):

Class ws.rag.bs.Service Extends Ens.BusinessService
{

Parameter SERVICENAME = "entrada";

Method entrada(pInput As ws.rag.msg.Request) As ws.rag.msg.Response [ WebMethod ]
{
              Set tSC=..SendRequestSync("bpRag",pInput,.tResponse)
              Quit tResponse
}

}

E o código do BP (Process)

Class ws.rag.bp.Process Extends Ens.BusinessProcessBPL [ ClassType = persistent, ProcedureBlock ]
{

/// BPL Definition
XData BPL [ XMLNamespace = "http://www.intersystems.com/bpl" ]
{
<process language='objectscript' request='ws.rag.msg.Request' response='ws.rag.msg.Response' height='2000' width='2000' >
<sequence xend='200' yend='350' >
<call name='boRag' target='boRag' async='0' xpos='200' ypos='250' >
<request type='ws.rag.msg.Request' >
<assign property="callrequest" value="request" action="set" languageOverride="" />
</request>
<response type='ws.rag.msg.Response' >
<assign property="response" value="callresponse" action="set" languageOverride="" />
</response>
</call>
</sequence>
</process>
}

Storage Default
{
<Type>%Storage.Persistent</Type>
}

}

 

E o código do BO (Operation):

 

Class ws.rag.bo.Operation Extends Ens.BusinessOperation [ ProcedureBlock ]
{

Method retrieve(pRequest As ws.rag.msg.Request, Output pResponse As ws.rag.msg.Response) As %Library.Status
{
 Set pResponse=##Class(ws.rag.msg.Response).%New()
 Set pResponse.status=1
 Set pResponse.mensagem=”OK”
 Set pResponse.sessionId=..%SessionId
 Set st=##Class(Vector.Util).RetrieveRelacional(“odbc_work”,pRequest.question,pRequest.sessionId)
 Set pResponse.resposta=st
 Quit $$$OK
}

XData MessageMap
{
<MapItems>
<MapItem MessageType=”ws.rag.msg.Request”>
 <Method>retrieve</Method>
 </MapItem>
</MapItems>
}

}

 

Na sequencia, as classes de Request e Response da integração:


Request:

 

Class ws.rag.msg.Request Extends Ens.Request
{

Property collectionName As %String;

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

Property sessionId As %String;

}

 

Response:

 

Class ws.rag.msg.Response Extends Ens.Response
{

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

Property status As %Boolean;

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

Property sessionId As %Integer;

 

}

 

E a classe da Production:

Class ws.rag.Production Extends Ens.Production
{

XData ProductionDefinition
{
<Production Name="ws.rag.Production" LogGeneralTraceEvents="false">
  <Description>Produção do Rag DEMO</Description>
  <ActorPoolSize>2</ActorPoolSize>
  <Item Name="ws.rag.bs.Service" Category="rag" ClassName="ws.rag.bs.Service" PoolSize="0" Enabled="true" Foreground="false" Comment="" LogTraceEvents="false" Schedule="">
  </Item>
  <Item Name="bpRag" Category="rag" ClassName="ws.rag.bp.Process" PoolSize="1" Enabled="true" Foreground="false" Comment="" LogTraceEvents="false" Schedule="">
  </Item>
  <Item Name="boRag" Category="rag" ClassName="ws.rag.bo.Operation" PoolSize="1" Enabled="true" Foreground="false" Comment="" LogTraceEvents="false" Schedule="">
  </Item>
</Production>
}

}

 

 

 

 

Ao ser executada a integração mantém os Requests e Responses armazenados permitindo a rastreabilidade no barramento, conforme vemos no trace a seguir:

 

Podemos ver no trace, por exemplo, que o tempo que a chamada a LLM levou para enviar os dados e devolver o SQL solicitado foi de aproximadamente 10s:

Podemos ver o retorno do BO após tratar a resposta da LLM no código python, para o nosso questionamento:

Assim, através da rastreabilidade da camada de interoperabilidade do Iris, podemos ver todo o fluxo de informação trafegado, os tempos decorridos, eventuais falhas e se for o caso, reprocessar alguma chamada, caso necessário.

A chamada do BO ao método em python passa a solicitação feita pelo usuário. O código em python através da busca vetorial encontra os registros mais semelhantes e os envia a LLM junto com a solicitação do usuário (no caso o modelo da nossa tabela), o histórico de conversa (se existir) e o prompt que são as orientações para balizar a atuação da LLM.

A LLM então gera o SQL que é devolvido ao método em python. O código então executa o SQL e formata a resposta para o padrão esperado, criando as listas de apresentação, gráficos ou downloads de acordo com o retorno aguardado pelo usuário.

Assim, através da aplicação CSP criada, podemos solicitar várias informações, como por exemplo, tabelas de respostas:

Ou gráficos:

Ou ainda, o download de informações:

Para o download, baixando e abrindo o arquivo temos os dados solicitados:

Estes exemplos mostram a leitura dos dados da tabela externa com o Gateway SQL do Iris e o seu uso com código escrito em python. Desta forma podemos utilizar todo o potencial dos dados, que não precisam estar armazenados dentro do Iris. Imagine poder montar uma estação de análise que colete dados de diversos sistemas e dê como resposta informações para tomada de decisão.

Podemos, por exemplo, ter dashboards visualizando dados dos diversos ambientes que compõem o ecossistema de uma empresa, previsões baseadas em algoritmos de ML, RAG para facilitar o levantamento de dados e muito mais.

O Iris pode ser o responsável por acessar, tratar e disponibilizar os dados dos diversos ambientes, com controle, segurança e rastreabilidade, graças às características de interoperabilidade, podendo utilizar código em COS e python, e ser acessado através de códigos em R, C, Java e muito mais. E tudo isso dentro do mesmo produto e sem a necessidade de duplicar ou mover dados entre ambientes.

Discussion (0)1
Log in or sign up to continue
Article
· Feb 11 7m read

Utilizando o Gateway SQL com Python, Vector Search e Interoperabilidade no InterSystems Iris - Parte 2 – Python e Vector Search

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

Vamos agora então consumir os dados do banco externo para calcular uma regressão polinomial. Para isso vamos através de um código em python executar um SQL que lerá nossa tabela do MySQL e transformará ela em um dataframe pandas:

ClassMethod CalcularRegressaoPolinomialODBC() As %String [ Language = python ]
{
    import iris
    import json
    import pandas as pd
    from sklearn.preprocessing import PolynomialFeatures
    from sklearn.linear_model import LinearRegression
    from sklearn.metrics import mean_absolute_error
    import numpy as np
    import matplotlib
    import matplotlib.pyplot as plt
    matplotlib.use("Agg")

    # Define Grau 2 para a regressão
    grau = 2
    
    # Recupera dados da tabela remota via ODBC
    rs = iris.sql.exec("select venda as x, temperatura as y from estat.fabrica")
    df = rs.dataframe()
   
    # Reformatando x para uma matriz 2D exigida pelo scikit-learn
    X = df[['x']]
    y = df['y']
    
    # Transformação para incluir termos polinomiais
    poly = PolynomialFeatures(degree=grau)
    X_poly = poly.fit_transform(X)

    # Inicializa e ajusta o modelo de regressão polinomial
    model = LinearRegression()
    model.fit(X_poly, y)

    # Extrai os coeficientes do modelo ajustado
    coeficientes = model.coef_.tolist()  # Coeficientes polinomiais
    intercepto = model.intercept_       # Intercepto
    r_quadrado = model.score(X_poly, y) # R Quadrado

    # Previsão para a curva de regressão
    x_pred = np.linspace(df['x'].min(), df['x'].max(), 100).reshape(-1, 1)  # Valores para a curva de regressão
    x_pred_poly = poly.transform(x_pred)  # Transformando para base polinomial
    y_pred = model.predict(x_pred_poly)
    
    # Calcula Y_pred baseado no X
    Y_pred = model.predict(X_poly)
            
    # Calcula MAE
    MAE = mean_absolute_error(y, Y_pred)
    
    # Geração do gráfico da Regressão
    plt.figure(figsize=(8, 6))
    plt.scatter(df['x'], df['y'], color='blue', label='Dados Originais')
    plt.plot(df['x'], df['y'], color='black', label='Linha dos Dados Originais')
    plt.scatter(df['x'], Y_pred, color='green', label='Dados Previstos')
    plt.plot(x_pred, y_pred, color='red', label='Curva da Regressão Polinomial')
    plt.title(f'Regressão Polinomial (Grau {grau})')
    plt.xlabel('X')
    plt.ylabel('Y')
    plt.legend()
    plt.grid(True)

    # Salvando o gráfico como imagem
    caminho_arquivo = 'c:\\temp\\RegressaoPolinomialODBC.png'
    plt.savefig(caminho_arquivo, dpi=300, bbox_inches='tight')
    plt.close()
    
    resultado = {
        'coeficientes': coeficientes,
        'intercepto': intercepto,
        'r_quadrado': r_quadrado,
        'MAE': MAE
    }

    return json.dumps(resultado)
}

A primeira ação que realizamos no código é a leitura os dados da nossa tabela externa via SQL e então os transformamos em um dataframe Pandas. Sempre lembrando que os dados estão fisicamente armazenados no MySQL e são acessados via ODBC através do Gateway SQL configurado no Iris. Com isso podemos utilizar as bibliotecas do python para cálculo e gráfico, conforme vemos no código.

Executando nossa rotina temos as informações do modelo gerado:

Nossa rotina também gera um gráfico que nos dá um suporte visual para a regressão polinomial. Vamos ver como o gráfico ficou:

Outra ação que podemos realizar com os dados que agora estão disponíveis é o uso do Vector Search e RAG com o uso de uma LLM. Para isso vamos vetorizar o modelo da nossa tabela e a partir daí pedir algumas informações a LLM.

Para mais informações sobre o uso de Vector Search no Iris veja o texto disponível em https://www.intersystems.com/vectorsearch/

Primeiro vamos vetorizar o modelo da nossa tabela. Abaixo o código com o qual realizamos esta tarefa:

ClassMethod IngestRelacional() As %String [ Language = python ]
{

    import json
    from langchain_iris import IRISVector
    from langchain_openai import OpenAIEmbeddings
    from langchain_text_splitters import RecursiveCharacterTextSplitter
    import iris    

    try:
    
        apiKey = iris.cls("Vector.Util").apikey()
        collectionName = "odbc_work"

        metadados_tabelas = [
            "Tabela: estat.fabrica; Colunas: chave(INT), venda(INT), temperatura(INT)"
        ]
        
        text_splitter = RecursiveCharacterTextSplitter(chunk_size=2048, chunk_overlap=0)
        documents=text_splitter.create_documents(metadados_tabelas)
            
        # Vetorizar as definições das tabelas
        vectorstore = IRISVector.from_documents(
        documents=documents,
        embedding=OpenAIEmbeddings(openai_api_key=apiKey),
        dimension=1536,
        collection_name=collectionName
        )
        
        return json.dumps({"status": True})
    except Exception as err:
        return json.dumps({"error": str(err)})
}

 

Note que não passamos para o código de ingest o conteúdo da tabela, e sim seu modelo. Desta forma a LLM é capaz de, ao receber as colunas e suas propriedades, definir um SQL de acordo com nossa solicitação.

Este código de ingest cria a tabela odbc_work que será utilizada para fazer a busca por similaridade no modelo da tabela, e a seguir solicitar a LLM que devolva um SQL. Para isso criamos uma API KEY na OpenAI e utilizamos o langchain_iris como biblioteca python. Para mais detalhes sobre o langchain_iris veja o link https://github.com/caretdev/langchain-iris

Após realizar o ingest da definição da nossa tabela teremos a tabela odbc_work gerada:

Agora vamos a nossa terceira parte que é o acesso de uma API REST que vai consumir os dados que estão vetorizados para montar um RAG.

Até logo!

Discussion (0)1
Log in or sign up to continue
Article
· Feb 11 4m read

Utilizando o Gateway SQL com Python, Vector Search e Interoperabilidade no InterSystems Iris - Parte 1 – Gateway SQL

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.

Para maiores detalhes sobre este componente veja a documentação que está disponível em https://docs.intersystems.com/irislatest/csp/docbook/DocBook.UI.Page.cls?KEY=BSQG_overview

Então vamos para as configurações necessárias:

Primeiro, para fazer a configuração do SQL Gateway no Iris vamos precisar configurar o acesso a um banco externo. Para nosso exemplo vamos utilizar uma instância MySQL sendo acessada via ODBC.

Instalamos então uma instância do MySQL em um servidor e nela criamos a tabela que será acessada no nosso exemplo:

 

 

 

 

 

 

Então populamos a tabela com informações. Abaixo um exemplo da tabela já com dados:

Agora vamos criar um DSN no Windows para realizar a conexão ao MySQL. Antes precisamos instalar o driver ODBC do MySQL no Windows. O driver pode ser facilmente obtido no site do próprio MySQL.

Após instalar o driver ODBC para o MySQL, abra o Gerenciador de Fonte de Dados ODBC no Windows:

 

Clique na aba “DSN de Sistema” e a seguir no botão Adicionar:

Selecione o driver MySQL ODBC ANSI e clique em Concluir.

 

Preencha a tela de configuração com nome do data source a ser criado, descrição, endereço IP e porta de comunicação do servidor do MySQL (padrão é a porta 3306 – verifique se sua instância MySQL está de fato utilizando esta porta de comunicação), o usuário e senha de acesso ao MySQL (crie no MySQL um usuário com permissão de acesso para as tabelas que deseja utilizar). Selecione o banco de dados a ser acessado:

 

Clique n botão de teste para verificar se a sua configuração está acessando a instancia do MySQL configurada no DSN:

 

Agora vamos fazer uma consulta via ODBC para verificar se tudo está OK na nossa estrutura. Vamos utilizar o Excel para isso. Abra o Excel, e vá em Dados->Obter Dados->De outras Fontes->Do ODBC:

Selecione o DSN que você criou para acessar o MySQL e a seguir selecione o esquema e a tabela que deseja verificar. No nosso caso vamos ver a tabela venda do esquema estat:

A seguir clique no botão Carregar e você verá os dados da sua tabela nas células do Excel:

 

Pronto. Já temos a nossa conexão ODBC criada e funcionando para realizar o acesso a nossa tabela remota. Agora vamos voltar ao Iris e realizar a configuração da conexão do SQL Gateway. Abra o Painel de Administração do Iris e vá em Administração do Sistema->Configuração->Conectividade->Conexões de SQL Gateway e clique no botão Criar Nova Conexão:

Informe os dados de acesso ao DSN conforme abaixo:

Tipo de Conexão

ODBC

Nome da Conexão

Informe um nome a seu critério

Selecione um DSN existente

Selecione o DSN criado para acesso ODBC ao MySQL

Usuário

Usuário de acesso (o mesmo do DSN)

Senha

Senha de acesso (a mesma que a do DSN)

 

Para o teste vamos deixar desmarcadas todas as opções da configuração, exceto a Não converter valores que não sejam caracteres:

Por fim clique em “Testar Conexão” para verificar se tudo está OK. Você verá o texto “Conexão teve sucesso.” caso tudo esteja configurado corretamente:

Uma vez criado o DSN e configurado o acesso do Gateway SQL podemos fazer a vinculação das tabelas para o Iris poder acessar os dados remotos. Para isso volte ao Portal de Administração e vá para Explorer do Sistema->SQL e mude para o namespace onde serão armazenadas as definições da classe que serão geradas:

Clique no link “Assistentes” e a seguir em “Vincular Tabela”. Você verá a tela do wizard de vinculação de tabelas do Iris:

Procure a conexão Gateway SQL que foi criada no passo anterior:

Selecione o esquema e a tabela que deseja vincular no Iris:

Clique em Avançar e selecione as colunas da tabela que deseja ter acesso:

Clique em Avançar e faça os ajustes de nomes e característica de leitura/gravação nos campos disponíveis:

Clique em Avançar e procure o campo que será a chave primária dos registros:

Selecione os campos que formam a chave primária do registro:

Clique em Salvar. Informe o nome da classe a ser criada e o nome da tabela SQL:

A seguir clique em Terminar.

A nossa classe no Iris foi criada. Abra o Studio e veja a classe:

Vamos testar o acesso aos dados fazendo uma consulta via SQL. Para isso vamos voltar ao Portal de Administração e vamos em Explorer do Sistema->SQL e vamos mudar para o namespace onde criamos nossa classe. Vamos então executar o SQL de consulta a nossa tabela vinculada:

Pronto! Já temos acesso aos dados de nossa tabela no MySQL. Lembrando que podemos realizar INSERT/UPDATE/DELETE ou então utilizar as sintaxes de manipulação de objetos do Iris agora que a tabela está vinculada, como vemos abaixo:

 

 

 

 

 

 

 

 

 

 

E usando a sintaxe de objetos do Iris:

 

Assim concluímos esta primeira parte já conseguindo acessar os dados do MySQL através do Iris utilizando o Gateway SQL.

Até a próxima parte do nosso artigo!

Discussion (0)1
Log in or sign up to continue