0 Seguidores · 47 Postagens

JSON (JavaScript Object Notation) é um formato de intercâmbio de dados leve. É fácil para humanos ler e escrever.

Artigo Yuri Marx · Out. 9, 2025 4m read

A linguagem ObjectScript possui um suporte incrível a JSON por meio de classes como %DynamicObject e %JSON.Adaptor. Esse suporte se deve à imensa popularidade do formato JSON em relação ao domínio anterior do XML. O JSON trouxe menos verbosidade à representação de dados e aumentou a legibilidade para humanos que precisavam interpretar conteúdo JSON. Para reduzir ainda mais a verbosidade e aumentar a legibilidade, o formato YAML foi criado. O formato YAML, muito fácil de ler, rapidamente se tornou o formato mais popular para representar configurações e parametrizações, devido à sua legibilidade

0
0 16
Artigo Heloisa Paiva · Ago. 25, 2025 3m read

Ao começar a usar o InterSystems IRIS ou Cache, os desenvolvedores frequentemente se deparam com três conceitos principais: Objetos Dinâmicos, Globals e Tabela Relacional. Cada um tem seu papel na construção de soluções escaláveis e fáceis de manter. Neste artigo, vamos percorrer exemplos de código práticos, destacar as melhores práticas e mostrar como esses conceitos se conectam.

1. Trabalhando com Objetos Dinâmicos

0
0 30
Artigo Larissa Prussak · Jun. 30, 2025 3m read

Olá, desenvolvedores!

Observando a avalanche de ferramentas para desenvolvedores movidas por IA e baseadas em vibe-coding que vêm surgindo quase todo mês, com recursos cada vez mais interessantes, eu fiquei me perguntando se seria possível aproveitá-las com o InterSystems IRIS. Pelo menos para construir um frontend. E a resposta é: sim! Pelo menos com a abordagem que eu segui.

Aqui está minha receita para construir a interface via prompting conectada ao backend IRIS:

  1. Tenha uma REST API no lado do IRIS, que siga uma especificação Open API (swagger).
  2. Gere a interface com alguma ferramenta de vibe-coding (por exemplo, Lovable) e aponte essa interface para o endpoint da REST API.
  3. Pronto!

Aqui está o resultado do meu próprio exercício — uma interface 100% criada via prompt conectada a uma REST API IRIS, que permite listar, criar, atualizar e excluir registros de uma classe persistente (Open Exchange,código do frontend, vídeo):

Qual é a receita em detalhes?

0
0 32
Artigo Julio Esquerdo · Jun. 7, 2025 18m read

Olá,

Neste artigo vamos ver o uso do python como linguagem de programação no InterSystems Iris. Para tal vamos usar como referência a versão Community 2025.1 que está disponível para ser baixada em https://download.intersystems.com mediante o login no ambiente. Para maiores informações sobre o download e instalação do Iris veja o link da comunidade https://community.intersystems.com/post/how-download-and-install-intersystems-iris

0
0 41
Artigo Larissa Prussak · Jun. 5, 2025 5m read

Por muito tempo, eu quis aprender o framework Django, mas sempre surgia algum projeto mais urgente que acabava tomando prioridade. Como muitos desenvolvedores, eu uso Python para projetos de machine learning, mas quando comecei a aprender programação para web, o PHP ainda dominava. Então, quando precisei escolher um framework mais robusto para criar aplicações web e publicar meu trabalho de machine learning, acabei voltando para o PHP. Durante um tempo, utilizei o framework Laravel para construir meus sites, e foi com ele que conheci o padrão Model-View-Controller (MVC) moderno de programação

0
0 32
Artigo Larissa Prussak · Jun. 5, 2025 3m read

O IRIS oferece suporte nativo para transformações CCDA e FHIR, mas o acesso e a visualização desses recursos exigem tempo considerável de configuração e conhecimento do produto. O aplicativo IRIS Interop DevTools foi desenvolvido para preencher essa lacuna, permitindo que implementadores comecem a utilizar e visualizar imediatamente as capacidades de transformação embutidas no produto.

Além do ambiente de transformação IRIS XML, XPath e CCDA, o pacote Interop DevTools agora inclui:

0
0 33
InterSystems Oficial Danusa Calixto · Abr. 3, 2025

Resumo de Alertas

Alerta ID Produto & Versões Afectadas Requisitos Explícitos
DP-439207  InterSystems IRIS® data platform 2024.3 (AIX) Instalações AIX Usando JSON e conjuntos de Caracteres Unicode non-Latin-1 
DP-439280  InterSystems IRIS 2024.3 (containers com IntegratedML)  IntegratedML Containers usando TensorFlow

Detalhes dos Alertas

DP-439207 - Problemas no Parser JSON Unicode em AIX

0
0 28
Artigo Heloisa Paiva · Mar. 7, 2025 7m read

Introdução

Uma API REST (Representational State Transfer ou Transferência de Estado Representacional) é uma interface que permite que diferentes aplicações se comuniquem entre si através do protocolo HTTP, usando operações padrão como GET, POST, PUT e DELETE. APIs REST são amplamente utilizadas no desenvolvimento de software para expor serviços acessíveis por outras aplicações, possibilitando a integração entre diferentes sistemas.

No entanto, para garantir que as APIs sejam fáceis de entender e usar, uma boa documentação é essencial. É aqui que o OpenAPI entra em cena.

0
0 43
Artigo Heloisa Paiva · Mar. 5, 2025 6m read

O que é JWT?

JWT (JSON Web Token) é um padrão aberto (RFC 7519) que oferece um método leve, compacto e auto-contido para transmitir informações de forma segura entre duas partes. É comumente usado em aplicações web para autenticação, autorização e troca de informações.

Um JWT é tipicamente composto por três partes:

1. Cabeçalho JOSE (JSON Object Signing and Encryption) 
2. Payload (Carga útil)
3. Assinatura

Essas partes são codificadas no formato Base64Url e concatenadas com pontos (.) separando-as.

Estrutura de um JWT

Cabeçalho

{ "alg": "HS256", "typ": "JWT"}

Payload

0
0 43
Artigo Heloisa Paiva · Fev. 25, 2025 3m read

Para um de nossos clientes, precisei integrar com o endpoint AFAS imageconnector/imageconnector/{imageId}?format={format}. Esse endpoint retorna uma mensagem JSON com a imagem como uma propriedade de string codificada em base64, além do mimetype da imagem.

/// Image Object
Class Mycustomer.Model.AfasGet.Image Extends (%SerialObject, %XML.Adaptor, %JSON.Adaptor)
{
/// file data (base64 encoded)
Property Filedata As %String(%JSONFIELDNAME = "filedata");

/// MimeType e.g. "image/jpeg"
Property MimeType As %String(%JSONFIELDNAME = "mimetype");
}

Na classe Message, tentamos lidar com isso da seguinte forma:

Property Image As Mycustomer.Model.AfasGet.Image;

/// AFAS GetImage response
/// get /imageconnector/{imageId}?format={format}
Method LoadFromResponse(httpResponse As %Net.HttpResponse, caller As %String = "") As %Status
{
	Set sc = $$$OK

	If $$$LOWER($Piece(httpResponse.ContentType,";",1))="application/json",httpResponse.StatusCode = "200" {
		set ..Image = ##class(Mycustomer.Model.AfasGet.Image).%New()
		set ..status = ..Image.%JSONImport(httpResponse.Data)
	}

	Return sc
}

Tudo isso funcionava bem até que, em algum momento, o tamanho do filedata se tornou maior que o $$$MaxStringLength (3.641.144), caso em que uma exceção MAXSTRING era levantada.

O próximo passo lógico foi alterar o tipo da propriedade filedata para %Stream.GlobalCharacter:

/// Image Object
Class Mycustomer.Model.AfasGet.Image Extends (%SerialObject, %XML.Adaptor, %JSON.Adaptor)
{
/// file data (base64 encoded)
Property Filedata As %Stream.GlobalCharacter(%JSONFIELDNAME = "filedata");

/// MimeType e.g. "image/jpeg"
Property MimeType As %String(%JSONFIELDNAME = "mimetype");
}

Mas isso não funcionou, %JSONImport() ainda gerava um erro MAXSTRING

Tentei então com Python, mas como não sou um especialista em Python, eventualmente desisti dessa abordagem.

Graças à resposta de Steven Hobbs https://community.intersystems.com/user/steven-hobbs em https://community.intersystems.com/post/maxstring-trying-read-string-json-object#comment-250216, aprendi então que é possível e direto recuperar propriedades de string JSON para um stream usando image.%Get("filedata", , "stream")):

Method LoadFromResponse(httpResponse As %Net.HttpResponse, caller As %String = "") As %Status
{
	Set sc = $$$OK

	If $$$LOWER($Piece(httpResponse.ContentType,";",1))="application/json",httpResponse.StatusCode = "200" {
		set ..Image = ##class(Mycustomer.Model.AfasGet.Image).%New()
		set image = {}.%FromJSON(httpResponse.Data)
		set ..Image.MimeType = image.mimetype
		set ..Image.Filedata = ##class(%Stream.GlobalCharacter).%New()
		do ..Image.Filedata.CopyFrom(image.%Get("filedata", , "stream"))
	}

	Return sc
}

Ainda estou perplexo sobre como eu poderia instruir a classe %JSON.Adaptor e usar a lógica interna para mapear para um stream. Se houver alguém por aí que saiba como fazer isso, por favor, me avise!

0
0 34
Artigo Julio Esquerdo · Fev. 18, 2025 34m read

API REST com Swagger no InterSystems IRIS

Olá,

O protocolo HTTP permite a obtenção de recursos, como documentos HTML. É a base de qualquer troca de dados na Web e um protocolo cliente-servidor, o que significa que as requisições são iniciadas pelo destinatário, geralmente um navegador da Web.

As API REST se beneficiam deste protocolo para trocar mensagens entre cliente e servidor. Isso torna as APIs REST rápidas, leves e flexíveis. As API REST utilizam os verbos HTTP GET, POST, PUT, DELETE e outros para indicar as ações que desejam realizar.

0
0 57
Artigo Julio Esquerdo · Fev. 12, 2025 5m read

Utilizando Flask, API REST e IAM com o InterSystems IRIS

Parte 3 – IAM

O InterSystems API Manager (IAM) é um componente que permite monitorar, controlar e gerir o tráfego de APIs baseadas em HTTP. Ele também atua como uma API gateway entre aplicações e servidores InterSystems IRIS. 

O documento publicado em https://docs.intersystems.com/irislatest/csp/docbook/DocBook.UI.Page.cls?KEY=PAGE_apimgr traz as informações sobre o produto.

0
0 30
Artigo Julio Esquerdo · Fev. 12, 2025 6m read

Utilizando Flask, API REST e IAM com o InterSystems IRIS

Parte 2 – Aplicativo Flask

Flask é um microframework de desenvolvimento web escrito em Python. Ele é conhecido por ser simples, flexível e permitir o desenvolvimento rápido de aplicações. 

A instalação do Flask é muito simples. Depois de ter o python instalado corretamente no seu sistema operacional precisamos instalar a biblioteca flask com o comando pip. Para o consumo de API REST é aconselhado o uso da biblioteca requests. O link a seguir traz um guia para a instalação do flask: https://flask.palletsprojects.com/en/stable/installation/

0
0 25
Artigo Julio Esquerdo · Fev. 12, 2025 10m read

Utilizando Flask, API REST e IAM com o InterSystems IRIS

Parte 1 – API REST

Olá,

Neste artigo vamos ver a implementação de uma API REST para realizar a manutenção de um CRUD, utilizando o Flask e o IAM.

Nesta primeira parte do artigo vamos ver a construção e publicação da API REST no Iris.

Primeiro, vamos criar a nossa classe persistente para armazenar os dados. Para isso vamos para o Iris e criamos nossa classe:

Class ERP.Cliente Extends (%Persistent, %Populate, %XML.Adaptor)

{

Property nome As %String;

Property idade As %Integer;

}

0
0 33
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 Heloisa Paiva · jan 30, 2025 5m read

Enquanto trabalhava para obter suporte JSON para algumas bibliotecas Python, descobri alguns recursos fornecidos pelo IRIS.

  • JSON_OBJECT - Uma função de conversão que retorna dados como um objeto JSON.
  • JSON_ARRAY - Uma função de conversão que retorna dados como um array JSON.
  • IS JSON -Determina se um valor de dados está no formato JSON.
  • JSON_TABLE Retorna uma tabela que pode ser usada em uma consulta SQL mapeando JSON.
  • JSONPath é uma linguagem de consulta para consultar valores em JSON.
0
0 46
Artigo Julio Esquerdo · Nov. 28, 2024 20m read

Usando o Python no InterSystems IRIS – Montando o Relatório de Análise Exploratória de Dados

Olá,

Neste artigo vamos ver como usar o python para realizar a análise exploratória de dados (Exploratory Data Analysis - EDA) em um dataframe.

EDA é uma etapa importante no ciclo de análise de dados, É quando você examina os dados para entender suas características e padrões.

0
0 90
Artigo Julio Esquerdo · Nov. 26, 2024 13m read

Usando o Python no InterSystems IRIS – Calculando uma Regressão Polinomial

Olá,

Neste artigo vamos ver como usar o python para calcular uma regressão polinomial no Iris.

A regressão polinomial é um modelo estatístico que é uma extensão da regressão linear. Ela é útil quando a relação entre as variáveis independente e dependente não é linear, sendo melhor definida como curva.

A regressão polinomial nos dá como resposta informações que podem ajudar a entender o modelo, assim como a regressão linear: coeficientes, o R2 e o intercepto.

0
0 128
Artigo Julio Esquerdo · Nov. 16, 2024 11m read

Usando o Python no InterSystems IRIS – Calculando uma Regressão Linear Simples

Olá,

Neste artigo vamos ver como usar o python para calcular uma regressão linear simples no Iris.

A regressão linear simples é um modelo estatístico que tem como objetivo apontar como será o comportamento de uma variável dependente (y) em relação a uma variável independente (x), ou seja, a regressão linear simples é uma maneira de verificar a relação entre duas variáveis.

1
0 125
Artigo Heloisa Paiva · Out. 24, 2024 7m read

fastapi_logo

Descrição

Este é um modelo para um aplicativo FastAPI que pode ser implantado no IRIS como um aplicativo Web nativo.

Instalação

  1. Clone o repositório
  2. Crie um ambiente virtual
  3. Instale os requisitos
  4. Execute o arquivo docker-compose
git clone
cd iris-fastapi-template
python3 -m venv .venv
source .venv/bin/activate
pip install -r requirements.txt
docker-compose up

Uso

A URL base é http://localhost:53795/fastapi/.

Endpoints

  • /iris - Retorna um objeto JSON com as 10 principais classes presentes no namespace IRISAPP.
  • /interop - Um endpoint de ping para testar a estrutura de interoperabilidade do IRIS.
  • /posts - Um endpoint CRUD simples para um objeto Post.
  • /comments - Um endpoint CRUD simples para um objeto Comentário.

Como desenvolver a partir deste template

Veja o artigo de introdução ao WSGI: wsgi-introduction.

TL;DR: Você pode ativar ou desativar o sinalizador DEBUG no portal de segurança para que as alterações sejam refletidas no aplicativo à medida que você desenvolve.

Apresentação do código

app.py

Este é o arquivo principal do aplicativo FastAPI. Ele contém o aplicativo FastAPI e as rotas.

from fastapi import FastAPI, Request

import iris

from grongier.pex import Director

# import models
from models import Post, Comment, init_db
from sqlmodel import Session,select

app = FastAPI()

# create a database engine
url = "iris+emb://IRISAPP"
engine = init_db(url)
  • from fastapi import FastAPI, Request - Importe a classe FastAPI e a classe Request
  • import iris - Importe o módulo IRIS.
  • from grongier.pex import Director: Importe a classe Director para vincular o aplicativo Flask ao framework de interoperabilidade do IRIS.
  • from models import Post, Comment, init_db - Importe os modelos e a função init_db.
  • from sqlmodel import Session,select - Importe a classe Session e a função select do módulo sqlmodel.
  • app = FastAPI() - Crie um aplicativo FastAPI.
  • url = "iris+emb://IRISAPP" -Defina o URL do namespace IRIS.
  • engine = init_db(url) - Crie um mecanismo de banco de dados para o ORM sqlmodel..

models.py

Este arquivo contém os modelos para o aplicativo.

from sqlmodel import Field, SQLModel, Relationship, create_engine

class Comment(SQLModel, table=True):
    id: int = Field(default=None, primary_key=True)
    post_id: int = Field(foreign_key="post.id")
    content: str
    post: "Post" = Relationship(back_populates="comments")

class Post(SQLModel, table=True):
    id: int = Field(default=None, primary_key=True)
    title: str
    content: str
    comments: list["Comment"] = Relationship(back_populates="post")

Não há muito a dizer aqui, apenas a definição dos modelos com chaves estrangeiras e relacionamentos.

A função init_db é usada para criar o mecanismo de banco de dados.

def init_db(url):

    engine = create_engine(url)

    # create the tables
    SQLModel.metadata.drop_all(engine)
    SQLModel.metadata.create_all(engine)

    # initialize database with fake data
    from sqlmodel import Session

    with Session(engine) as session:
        # Create fake data
        post1 = Post(title='Post The First', content='Content for the first post')
        ...
        session.add(post1)
        ...
        session.commit()

    return engine
  • engine = create_engine(url) - Crie um mecanismo de banco de dados.
  • SQLModel.metadata.drop_all(engine) - Exclua todas as tabelas.
  • SQLModel.metadata.create_all(engine) - Crie todas as tabelas.
  • with Session(engine) as session: - Crie uma sessão para interagir com o banco de dados.
  • post1 = Post(title='Post The First', content='Content for the first post')- Crie um objeto Post..
  • session.add(post1) -Adicione o objeto Post à sessão.
  • session.commit() -Confirme as alterações no banco de dados.
  • return engine - Retorne o mecanismo de banco de dados.

/iris endpoint

######################
# IRIS Query exemplo #
######################

@app.get("/iris")
def iris_query():
    query = "SELECT top 10 * FROM %Dictionary.ClassDefinition"
    rs = iris.sql.exec(query)
    # Convert the result to a list of dictionaries
    result = []
    for row in rs:
        result.append(row)
    return result
  • @app.get("/iris") - Defina uma rota GET para o endpoint /iris .
  • query = "SELECT top 10 * FROM %Dictionary.ClassDefinition" -Defina a consulta para obter as 10 principais classes no namespace IRIS.
  • rs = iris.sql.exec(query) - Execute a consulta..
  • result = [] - Crie uma lista vazia para armazenar os resultados.
  • for row in rs: - Itere sobre o conjunto de resultados.
  • result.append(row) - Adicione a linha à lista de resultados.
  • return result - Retorne a lista de resultados.

/interop endpoint

########################
# IRIS interop exemplo #
########################
bs = Director.create_python_business_service('BS')

@app.get("/interop")
@app.post("/interop")
@app.put("/interop")
@app.delete("/interop")
def interop(request: Request):
    
    rsp = bs.on_process_input(request)

    return rsp

  • bs = Director.create_python_business_service('BS') - Crie um business service Python. -Deve ser criado fora da definição da rota para evitar múltiplas instâncias do serviço de negócios.
  • @app.get("/interop") - Define uma rota GET para o endpoint /interop.
  • @app.post("/interop") - Define uma rota POST para o endpoin /interop .
  • ...
  • def interop(request: Request): - Define o manipulador da rota.
  • rsp = bs.on_process_input(request) - Chame o método on_process_input do business service.
  • return rsp - Retorne a resposta.

/posts endpoint

############################
# operações CRUD de posts    #
############################

@app.get("/posts")
def get_posts():
    with Session(engine) as session:
        posts = session.exec(select(Post)).all()
        return posts
    
@app.get("/posts/{post_id}")
def get_post(post_id: int):
    with Session(engine) as session:
        post = session.get(Post, post_id)
        return post
    
@app.post("/posts")
def create_post(post: Post):
    with Session(engine) as session:
        session.add(post)
        session.commit()
        return post

Este endpoint é usado para realizar operações CRUD no objeto Post.

Não há muito a dizer aqui, apenas a definição das rotas para obter todos os posts, obter um post por ID e criar um post.

Tudo é feito usando o ORM sqlmodel.

/comments endpoint

############################
# operações  CRUD de comments #
############################


@app.get("/comments")
def get_comments():
    with Session(engine) as session:
        comments = session.exec(select(Comment)).all()
        return comments
    
@app.get("/comments/{comment_id}")
def get_comment(comment_id: int):
    with Session(engine) as session:
        comment = session.get(Comment, comment_id)
        return comment
    
@app.post("/comments")
def create_comment(comment: Comment):
    with Session(engine) as session:
        session.add(comment)
        session.commit()
        return comment

Este endpoint é usado para realizar operações CRUD no objeto Comment.

Não há muito a dizer aqui, apenas a definição das rotas para obter todos os comentários, obter um comentário por ID e criar um comentário.

Tudo é feito usando o ORM sqlmodel.

Solução de Problemas

Como executar o aplicativo FastAPI em modo autônomo

Você sempre pode executar um aplicativo Flask autônomo com o seguinte comando:

python3 /irisdev/app/community/app.py

Observação: você deve estar dentro do contêiner para executar este comando.

docker exec -it iris-fastapi-template-iris-1 bash

Reinicie o aplicativo no IRIS

Fique no modo DEBUG, faça várias chamadas para o aplicativo e as alterações serão refletidas no aplicativo.

Como acessar o Portal de Gerenciamento do IRIS

Você pode acessar o Portal de Gerenciamento do IRIS acessando http://localhost:53795/csp/sys/UtilHome.csp.

Execute este template localmente

Para isso, você precisa ter o IRIS instalado em sua máquina.

Em seguida, você precisa criar um namespace chamado IRISAPP.

Instale os requisitos.

Instale IoP :

#init iop
iop --init

# load production
iop -m /irisdev/app/community/interop/settings.py

# start production
iop --start Python.Production

Configure o aplicativo no portal de segurança.

0
0 43
Artigo Heloisa Paiva · Out. 22, 2024 9m read

django_logo

Descrição

Este é um modelo para um aplicativo Django que pode ser implantado no IRIS como um aplicativo Web nativo.

Instalação

  1. Clone o repositório
  2. Crie um ambiente virtual
  3. Instale os requisitos
  4. Rode o arquivo docker-compose
git clone
cd iris-django-template
python3 -m venv .venv
source .venv/bin/activate
pip install -r requirements.txt
docker-compose up

Uso

A URL base é http://localhost:53795/django/.

Endpoints

  • /iris - Retorna um objeto JSON com as 10 principais classes presentes no namespace IRISAPP.
  • /interop - Um endpoint de ping para testar a estrutura de interoperabilidade do IRIS.
  • /api/posts -Um endpoint CRUD simples para um objeto Post.
  • /api/comments - Um endpoint CRUD simples para um objeto Comment.

Como desenvolver deste modelo

Veja o artigo de introdução ao WSGI: wsgi-introduction.

TL;DR: Você pode ativar ou desativar o sinalizador DEBUG no portal de segurança para que as alterações sejam refletidas no aplicativo à medida que você desenvolve.

Apresentação do código

A aplicação Django é estruturada como se segue:

  • app - Pasta do projeto Django
    • app - Pasta da aplicação Django para configuração
      • settings.py - Arquivo de definições Django
      • urls.py - Arquivo de configuração de URL Django para conectar as visualizações às URLs
      • wsgi.py - Arquivo do Django WSGI
      • asgi.py - Arquivo do Django AGI
    • community - Pasta da aplicação Django para o aplicativo da comunidade, com CRUD nos objetos de Post e Comment
      • models.py - Arquivo de modelos do Djando para os objetos Post e Comment
      • views.py - Arquivo de visualizações Django para cessar os objetos Post e Comment
      • serializers.py - Arquivo Django de serializadores para os objetos Post e Comentário. * admin.py - Arquivo Django de administração para adicionar CRUD à interface administrativa.
      • migrations - Pasta Django de migrações para construir o banco de dados.
      • fixtures - Pasta Django de fixtures com dados de demonstração
    • sqloniris - Pasta do aplicativo Django para o aplicativo SQL no IRIS.
      • views.py - Arquivo Django de views para consultar o namespace IRISAPP.
      • apps.py - Arquivo de configuração do aplicativo Django.
    • interop - Pasta do aplicativo Django para o aplicativo de interoperabilidade.
      • views.py - Arquivo Django de views para testar a estrutura de interoperabilidade.
      • apps.py - Arquivo de configuração do aplicativo Django.
    • manage.py - Arquivo de gerenciamento Django.

app/settings.py

Este arquivo contém as configurações Django para o aplicativo.

...

# Definição de aplicação

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'community',
    'sqloniris',
    'interop',
    'rest_framework'
]

...

REST_FRAMEWORK = {
    # Use as permissões padrão do Django `django.contrib.auth` ,
    # ou permita acesso de apenas leitura para usuários não autenticados
    'DEFAULT_PERMISSION_CLASSES': [
        'rest_framework.permissions.DjangoModelPermissionsOrAnonReadOnly'
    ],
    'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.LimitOffsetPagination',
    'PAGE_SIZE': 20
}

...

DATABASES = {
    "default": {
        "ENGINE": "django_iris",
        "EMBEDDED": True,
        "NAMESPACE": "IRISAPP",
        "USER":"SuperUser",
        "PASSWORD":"SYS",
    }
}

Algumas definições importantes para notar:

  • INSTALLED_APPS - Contém a lista de aplicativos instalados no projeto Django.
  • community - O aplicativo Django para as operações CRUD nos objetos Post e Comentário.
  • sqloniris - TO aplicativo Django para as operações SQL no IRIS.
  • interop - O aplicativo Django para as operações de interoperabilidade.
  • rest_framework - O framework Django REST para a API REST.
  • REST_FRAMEWORK - Contém as configurações para o framework Django REST.
    • DEFAULT_PERMISSION_CLASSES - Somente usuários autenticados podem realizar operações CRUD.
    • DEFAULT_PAGINATION_CLASS - A classe de paginação para a API REST.
  • DATABASES - Contém as configurações para a conexão com o banco de dados IRIS.
    • Aqui estamos usando o mecanismo django_iris para conectar ao banco de dados IRIS.

app/urls.py

Este arquivo contém a configuração de URL para o aplicativo Django.

from django.contrib import admin
from django.urls import path,include
from rest_framework import routers
from community.views import PostViewSet, CommentViewSet
from sqloniris.views import index
from interop.views import index as interop_index

router = routers.DefaultRouter()
router.register(r'posts', PostViewSet)
router.register(r'comments', CommentViewSet)


urlpatterns = [
    path('admin/', admin.site.urls),
    path('api/', include(router.urls)),
    path('iris/', index),
    path('interop/', interop_index)
]
  • router - Contém o roteador padrão para a API REST.
  • routeer.register - Registra os viewsets Post e Comentário no roteador.
  • urlpatterns - Contém os padrões de URL para o aplicativo Django
    • /admin/ - A interface administrativa Django.
    • /api/ -A API REST para os objetos Post e Comentário.
    • /iris/ - O endpoint SQL no IRIS.
    • /interop/ - O endpoint de interoperabilidade.

app/wsgi.py

Este arquivo contém a configuração WSGI para o aplicativo Django.

Este é o arquivo que temos que fornecer ao IRIS para executar o aplicativo Django.

Na seção Security->Applications->Web Applications, temos que fornecer o caminho para este arquivo.

  • Application Name
    • app.wsgi
  • Callable Name
    • application
  • WSGI App directory
    • /irisdev/app/app

community/models.py

Este arquivo contém os modelos Django para os objetos Post e Comentário.

from django.db import models

# Create your models here.
class Post(models.Model):
    title = models.CharField(max_length=100)
    content = models.TextField()

class Comment(models.Model):
    content = models.TextField()
    post = models.ForeignKey(Post, on_delete=models.CASCADE, related_name='comments')
  • Post - O modelo para o objeto Post.
    • title - O título do post.
    • content - O conteúdo do post.
  • Comment - O modelo para o objeto Comentário.
    • content - O conteúdo do comentário.
    • post - A chave estrangeira para o objeto Post.
    • related_name - O nome relacionado para os comentários.

community/seializers.py

Este arquivo contém os serializadores Django para os objetos Post e Comentário.

Usando o framework Django REST, podemos serializar os modelos Django em objetos JSON.

from rest_framework import serializers
from community.models import Post, Comment

class PostSerializer(serializers.ModelSerializer):
    class Meta:
        model = Post
        fields = ('id', 'title', 'content', 'comments')

class CommentSerializer(serializers.ModelSerializer):
    class Meta:
        model = Comment
        fields = ('id', 'content', 'post')
  • PostSerializer -O serializador para o objeto Post.
  • CommentSerializer -O serializador para o objeto Comentário.
  • fields - Os campos a serem serializados.

community/views.py

Este arquivo contém as views Django para os objetos Post e Comentário.

Usando o framework Django REST, podemos criar operações CRUD para os modelos Django.

from django.shortcuts import render
from rest_framework import viewsets

# Import the Post and Comment models
from community.models import Post, Comment

# Import the Post and Comment serializers
from community.serializers import PostSerializer, CommentSerializer

# Create your views here.
class PostViewSet(viewsets.ModelViewSet):
    queryset = Post.objects.all()
    serializer_class = PostSerializer

class CommentViewSet(viewsets.ModelViewSet):
    queryset = Comment.objects.all()
    serializer_class = CommentSerializer
  • PostViewSet - O viewset para o objeto Post.
  • CommentViewSet - O viewset para o objeto Comentário.
  • queryset - O queryset para o viewset.
  • serializer_class - A classe de serializador para o viewset.

sqloniris/views.py

Este arquivo contém as views Django para as operações SQL no IRIS.

from django.http import JsonResponse

import iris

def index(request):
    query = "SELECT top 10 * FROM %Dictionary.ClassDefinition"
    rs = iris.sql.exec(query)
    # Convert the result to a list of dictionaries
    result = []
    for row in rs:
        result.append(row)
    return JsonResponse(result, safe=False)
  • index - A view para a operação SQL no IRIS.
  • query - A consulta SQL a ser executada no banco de dados IRIS.
  • rs - O conjunto de resultados da consulta.
  • result - A lista de listas do conjunto de resultados.
  • JsonResponse - A resposta JSON para a view, safe é definido como False para permitir lista de listas.

interop/views.py

Este arquivo contém as views Django para as operações de interoperabilidade.

from django.http import HttpResponse

from grongier.pex import Director

bs = Director.create_python_business_service('BS')

def index(request):
    result = bs.on_process_input(request)
    return HttpResponse(result, safe=False)
  • bs - O objeto de serviço de negócios criado usando a classe Director .
  • index -A view para a operação de interoperabilidade.
  • result - A view para a operação de interoperabilidade.

Observação: não usamos JsonResponse para simplificar o código, podemos usá-lo se quisermos retornar um objeto JSON.

Solução de Problemas

Como executar o aplicativo Django em modo autônomo

Para executar o aplicativo Django em modo autônomo, podemos usar o seguinte comando:

cd /irisdev/app/app
python3 manage.py runserver 8001

Isso executará o aplicativo Django na porta padrão 8001.

Observação: você deve estar dentro do contêiner para executar este comando.

docker exec -it iris-django-template-iris-1 bash

Reiniciando o aplicativo no IRIS

Esteja no modo DEBUG, faça várias chamadas para o aplicativo e as alterações serão refletidas no aplicativo.

Como acessar o Portal de Gerenciamento do IRIS

Você pode acessar o Portal de Gerenciamento do IRIS acessando http://localhost:53795/csp/sys/UtilHome.csp.

Executar este template localmente

Para isso, você precisa ter o IRIS instalado em sua máquina.

Em seguida, você precisa criar um namespace chamado IRISAPP.

Instale os requisitos.

# Move to the app directory
cd /irisdev/app/app

# python manage.py flush --no-input
python3 manage.py migrate
# create superuser
export DJANGO_SUPERUSER_PASSWORD=SYS
python3 manage.py createsuperuser --no-input --username SuperUser --email admin@admin.fr

# load demo data
python3 manage.py loaddata community/fixtures/demo.json

# collect static files
python3 manage.py collectstatic --no-input --clear

# init iop
iop --init

# load production
iop -m /irisdev/app/app/interop/settings.py

# start production
iop --start Python.Production

Como servir arquivos estáticos

Para servir os arquivos estáticos no aplicativo Django, podemos usar o seguinte comando:

cd /irisdev/app
python3 manage.py collectstatic

Isso coletará os arquivos estáticos do aplicativo Django e os servirá no diretório /irisdev/app/static.

Para publicar os arquivos estáticos no IRIS, configure a seçãoSecurity->Applications->Web Applications.

web_applications

0
0 35
Artigo Heloisa Paiva · Out. 20, 2024 6m read

Flask_logo

Descrição

Este é um modelo para um aplicativo Flask que pode ser implantado no IRIS como um aplicativo Web nativo.

Instalação

  1. Clone o repositório
  2. Crie um ambiente virtual
  3. Instale os requisitos
  4. Rode o arquivo docker-compose
git clone
cd iris-flask-template
python3 -m venv .venv
source .venv/bin/activate
pip install -r requirements.txt
docker-compose up

Uso

A URL de base http://localhost:53795/flask/.

Endpoints

  • /iris - Retorna um objeto JSON com as 10 principais classes presentes no namespace IRISAPP.
  • /interop - Um endpoint de ping para testar o framework de interoperabilidade do IRIS
  • /posts - Um simples enpoint CRUD para um objeto de Post
  • /comments - Um enpoint simples de CRUD para o objeto de comentário

Como desenvolver deste template

Veja o artigo de introdução ao WSGI wsgi-introduction.

TL;DR: Você pode ativar ou desativar o sinalizador DEBUG no portal de segurança para que as alterações sejam refletidas no aplicativo à medida que você desenvolve.

Apresentação do código

app.py

Este é o arquivo principal do aplicativo. Ele contém o aplicativo Flask e os endpoints.

from flask import Flask, jsonify, request
from models import Comment, Post, init_db

from grongier.pex import Director

import iris

app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = 'iris+emb://IRISAPP'

db = init_db(app)
  • from flask import Flask, jsonify, request: Importa a livraria Flask
  • from models import Comment, Post, init_db: Importa os modelos e a função de inicialização de base de dados
  • from grongier.pex import Director: Importa a classe Director para vincular o app flask à framework de interoperabilidade do IRIS
  • import iris: Importa a livraria IRIS
  • app = Flask(__name__): Cria uma aplicação Flask
  • app.config['SQLALCHEMY_DATABASE_URI'] = 'iris+emb://IRISAPP': Define o URI da base de dados ao namespace IRISAPP
    • O esquema de URI iris+emb é usado para conectar ao IRIS como uma conexão embutida (sem necessidade de uma instância IRIS separada
  • db = init_db(app): Inicialize a base de dados com aplicação Flask.

models.py

O arquivo contem os modelos SQLAlchemy para a aplicação.

from dataclasses import dataclass
from typing import List
from flask_sqlalchemy import SQLAlchemy

db = SQLAlchemy()

@dataclass
class Comment(db.Model):
    id:int = db.Column(db.Integer, primary_key=True)
    content:str = db.Column(db.Text)
    post_id:int = db.Column(db.Integer, db.ForeignKey('post.id'))

@dataclass
class Post(db.Model):
    __allow_unmapped__ = True
    id:int = db.Column(db.Integer, primary_key=True)
    title:str = db.Column(db.String(100))
    content:str = db.Column(db.Text)
    comments:List[Comment] = db.relationship('Comment', backref='post')

Não há muito o que dizer aqui, os modelos são definidos como classes de dados e são subclasses da classe db.Model

O uso do atributo __allow_unmapped_ é necessário para permitir a criação do objeto Post sem o atributo comments

dataclasses são usadas para ajudar com a serialização de objetos ao JSON

A função init_db inicializa a base de dados com a aplicação Flask.

def init_db(app):
    db.init_app(app)

    with app.app_context():
        db.drop_all()
        db.create_all()
        # Create fake data
        post1 = Post(title='Post The First', content='Content for the first post')
        ...
        db.session.add(post1)
        ...
        db.session.commit()
    return db
  • db.init_app(app): Inicializa a base de dados com a aplicação Flask
  • with app.app_context(): Cria um contexto para a aplicação
  • db.drop_all(): Descarta todas as tabelas na base de dados
  • db.create_all(): Cria todas as tabelas na base de dados
  • Cria dados falsos para a aplicação
  • retorna o objeto de base de dados

/iris endpoint

######################
# IRIS Query exemplo#
######################

@app.route('/iris', methods=['GET'])
def iris_query():
    query = "SELECT top 10 * FROM %Dictionary.ClassDefinition"
    rs = iris.sql.exec(query)
    # Converte o resultado em uma lista de dicionários
    result = []
    for row in rs:
        result.append(row)
    return jsonify(result)

Esse endpoint executa uma query na base de dados IRIS e retorna as top 10 classes presentes no namespace IRISAPP

/interop endpoint

########################
# IRIS interop exemplo #
########################
bs = Director.create_python_business_service('BS')

@app.route('/interop', methods=['GET', 'POST', 'PUT', 'DELETE'])
def interop():
    
    rsp = bs.on_process_input(request)

    return jsonify(rsp)

Este endpoint é usado para testar a estrutura de interoperabilidade do IRIS. Ele cria um objeto de Serviço de Negócio e o vincula ao aplicativo Flask.

Observação: O objeto bs deve estar fora do escopo da solicitação para mantê-lo ativo.

  • bs = Director.create_python_business_service('BS'): Cria um objeto Business Service chamado 'BS'
  • rsp = bs.on_process_input(request): Chama o método on_process_input do objeto Business Service com o objeto de requisição como um argumento

/posts endpoint

############################
# operações CRUD para posts    #
############################

@app.route('/posts', methods=['GET'])
def get_posts():
    posts = Post.query.all()
    return jsonify(posts)

@app.route('/posts', methods=['POST'])
def create_post():
    data = request.get_json()
    post = Post(title=data['title'], content=data['content'])
    db.session.add(post)
    db.session.commit()
    return jsonify(post)

@app.route('/posts/<int:id>', methods=['GET'])
def get_post(id):
    ...

Este endpoint é usado para realizar operações CRUD no objeto Post

Graças ao módulo dataclasses, o objeto Post pode ser facilmente serializado para JSON.

Aqui, usamos o método query do sqlalchemy para obter todos os posts e os métodos add e commit para criar um novo post

/comments endpoint

############################
# operações CRUD para comentários  #
############################

@app.route('/comments', methods=['GET'])
def get_comments():
    comments = Comment.query.all()
    return jsonify(comments)

@app.route('/comments', methods=['POST'])
def create_comment():
    data = request.get_json()
    comment = Comment(content=data['content'], post_id=data['post_id'])
    db.session.add(comment)
    db.session.commit()
    return jsonify(comment)

@app.route('/comments/<int:id>', methods=['GET'])
def get_comment(id):
    ...

Este endpoint é usado para realizar operações CRUD no objeto Comment.

O objeto Comment está vinculado ao objeto Post por uma chave estrangeira.

Solução de Problemas

Como executar o aplicativo Flask em modo autônomo

Você sempre pode executar um aplicativo Flask autônomo com o seguinte comando:

python3 /irisdev/app/community/app.py

Nota: você deve estar dentro do container para rodar este comando

docker exec -it iris-flask-template-iris-1 bash

Reinicie a aplicação no IRIS

Esteja no modo DEBUG, faça várias chamadas para o aplicativo e as alterações serão refletidas no aplicativo.

Como acessar o Portal de Gerenciamento do IRIS

Você pode acessar o Portal de Gerenciamento do IRIS acessandohttp://localhost:53795/csp/sys/UtilHome.csp.

Rode este template localmente

Para isso, você precisa ter o IRIS instalado em sua máquina.

Em seguida, você precisa criar um namespace chamado IRISAPP.

Instale os requisitos.

Instale IoP :

#init iop
iop --init

# carregue a produção 
iop -m /irisdev/app/community/interop/settings.py

# iniicie a produção
iop --start Python.Production

Configure a aplicação no portal de Segurança

0
0 48
Artigo Heloisa Paiva · Jul. 23, 2024 8m read

image

Olá Comunidade,

Nesse artigo, demonstrarei os seguintes passos para criar seu próprio chatbot utilizando spaCy (spaCy é uma biblioteca de software de código aberto para o processamento avançado de linguagem natural, escrita nas linguagens de programação Python e Cython):

  • Passo 1: Instalar as livrarias necessárias

  • Passo 2: Criar o arquivo de padrões e respostas

  • Passo 3: Treinar o modelo

  • Passo 4: Criar uma aplicação ChatBot baseada no modelo treinado

Comecemos

0
0 104
Artigo Nicole Raimundo · Maio 16, 2024 9m read

DNA Similarity and Classification é uma API REST utilizando a tecnologia InterSystems Vector Search para investigar semelhanças genéticas e classificar eficientemente sequências de DNA. Este é um aplicativo que utiliza técnicas de inteligência artificial, como aprendizado de máquina, aprimorado por recursos de pesquisa vetorial, para classificar famílias genéticas e identificar DNAs semelhantes conhecidos a partir de um DNA de entrada desconhecido.

Análise K-mer: Fundamentos em Análise de Sequência de DNA

1
1 133
Artigo Heloisa Paiva · Mar. 15, 2024 6m read

Introdução

Nas próximas semanas, meus colegas de trabalho estão planejando começar a usar VSCode para programar com os produtos InterSystems. Entre as várias vantagens disso, eu gostaria de salientar a possibilidade de se conectar com outras tecnologias, como o GitHub, com facilidade. Além disso, o VSCode também oferece uma extensa loja de extensões, onde você pode achar vários recursos adicionais gratuitos que fazem a programação mais rápida e eficiente. Por último e não menos importante, para conquistar os corações de todo desenvolvedor, é Open Source.

0
0 198
Artigo Danusa Calixto · jan 10, 2024 12m read

Temos um delicioso conjunto de dados com receitas escritas por vários usuários do Reddit, porém, a maioria das informações é texto livre, como o título ou a descrição de um post. Vamos descobrir como carregar o conjunto de dados facilmente, extrair algumas características e analisá-las usando recursos do modelo de linguagem grande da OpenAI no Embedded Python e no framework Langchain.

Carregando o conjunto de dados

Primeiro de tudo, precisamos carregar o conjunto de dados ou podemos só nos conectar a ele?

Há diferentes maneiras de alcançar isso: por exemplo, é possível usar o CSV Record Mapper em uma produção de interoperabilidade ou até em aplicativos legais do OpenExchange, como csvgen.

Vamos usar o Foreign Tables. Um recurso bastante útil para projetar dados armazenados fisicamente em outro lugar no IRIS SQL. Podemos usar isso para ter uma primeira visão dos arquivos do conjunto de dados.

Criamos um Foreign Server:

CREATE FOREIGN SERVER dataset FOREIGN DATA WRAPPER CSV HOST '/app/data/'

E, em seguida, uma Foreign Table que se conecta ao arquivo CSV:

CREATE FOREIGN TABLE dataset.Recipes (
  CREATEDDATE DATE,
  NUMCOMMENTS INTEGER,
  TITLE VARCHAR,
  USERNAME VARCHAR,
  COMMENT VARCHAR,
  NUMCHAR INTEGER
) SERVER dataset FILE 'Recipes.csv' USING
{
  "from": {
    "file": {
       "skip": 1
    }
  }
}

É isso, imediatamente podemos executar consultas SQL em "dataset.Recipes": image

## Quais dados são necessários? O conjunto de dados é interessante e estamos com fome. No entanto, se quisermos decidir uma receita para cozinhar, será preciso mais algumas informações que possamos usar para análise.

Vamos trabalhar com duas classes persistentes (tabelas):

  • yummy.data.Recipe: uma classe que contém o título e a descrição da receita e algumas outras propriedades que queremos extrair e analisar, por exemplo, Score, Difficulty, Ingredients, CuisineType, PreparationTime (nota, dificuldade, ingredientes, tipo de culinária, tempo de preparo)
  • yummy.data.RecipeHistory: uma classe simples para registrar o que estamos fazendo com a receita

Podemos agora carregar nossas tabelas "yummy.data*" com o conteúdo do conjunto de dados:

do ##class(yummy.Utils).LoadDataset()

Parece bom, mas ainda precisamos descobrir como vamos gerar os dados para os campos Score, Difficulty, Ingredients, PreparationTime e CuisineType.

## Analise as receitas Queremos processar cada título e descrição de receita e:

  • Extrair informações como Difficulty, Ingredients, CuisineType etc.
  • Criar nossa própria nota com base em nossos critérios para que possamos decidir o que queremos cozinhar.

Vamos usar o seguinte:

LLM (modelos de linguagem grande) são realmente uma ótima ferramenta para processar linguagem natural.

LangChain está pronto para uso no Python, então podemos usá-lo diretamente no InterSystems IRIS usando o Embedded Python.

A classe "SimpleOpenAI" completa fica assim:

/// Análise simples da OpenAI para receitas
Class yummy.analysis.SimpleOpenAI Extends Analysis
{

Property CuisineType As %String;

Property PreparationTime As %Integer;

Property Difficulty As %String;

Property Ingredients As %String;

/// Execute
/// Você pode tentar isto a partir de um terminal:
/// set a = ##class(yummy.analysis.SimpleOpenAI).%New(##class(yummy.data.Recipe).%OpenId(8))
/// do a.Run()
/// zwrite a
Method Run()
{
    try {
        do ..RunPythonAnalysis()

        set reasons = ""

        // meus tipos de culinária favoritos
        if "spanish,french,portuguese,italian,korean,japanese"[..CuisineType {
            set ..Score = ..Score + 2
            set reasons = reasons_$lb("It seems to be a "_..CuisineType_" recipe!")
        }

        // não quero passar o dia todo cozinhando :)
        if (+..PreparationTime < 120) {
            set ..Score = ..Score + 1
            set reasons = reasons_$lb("You don't need too much time to prepare it") 
        }
        
        // bônus para ingredientes favoritos!
        set favIngredients = $listbuild("kimchi", "truffle", "squid")
        for i=1:1:$listlength(favIngredients) {
            set favIngred = $listget(favIngredients, i)
            if ..Ingredients[favIngred {
                set ..Score = ..Score + 1
                set reasons = reasons_$lb("Favourite ingredient found: "_favIngred)
            }
        }

        set ..Reason = $listtostring(reasons, ". ")

    } catch ex {
        throw ex
    }
}

/// Atualize a receita com o resultado da análise
Method UpdateRecipe()
{
    try {
        // chame a implementação de classe mãe primeiro
        do ##super()

        // adicione resultados de análises da OpenAI específicos
        set ..Recipe.Ingredients = ..Ingredients
        set ..Recipe.PreparationTime = ..PreparationTime
        set ..Recipe.Difficulty = ..Difficulty
        set ..Recipe.CuisineType = ..CuisineType

    } catch ex {
        throw ex
    }
}

/// Execute a análise usando o embedded Python + Langchain
/// do ##class(yummy.analysis.SimpleOpenAI).%New(##class(yummy.data.Recipe).%OpenId(8)).RunPythonAnalysis(1)
Method RunPythonAnalysis(debug As %Boolean = 0) [ Language = python ]
{
    # load OpenAI APIKEY from env
    import os
    from dotenv import load_dotenv, find_dotenv
    _ = load_dotenv('/app/.env')

    # account for deprecation of LLM model
    import datetime
    current_date = datetime.datetime.now().date()
    # date after which the model should be set to "gpt-3.5-turbo"
    target_date = datetime.date(2024, 6, 12)
    # set the model depending on the current date
    if current_date > target_date:
        llm_model = "gpt-3.5-turbo"
    else:
        llm_model = "gpt-3.5-turbo-0301"

    from langchain.chat_models import ChatOpenAI
    from langchain.prompts import ChatPromptTemplate
    from langchain.chains import LLMChain

    from langchain.output_parsers import ResponseSchema
    from langchain.output_parsers import ResponseSchema

    # init llm model
    llm = ChatOpenAI(temperature=0.0, model=llm_model)

    # prepare the responses we need
    cuisine_type_schema = ResponseSchema(
        name="cuisine_type",
        description="What is the cuisine type for the recipe? \
                     Answer in 1 word max in lowercase"
    )
    preparation_time_schema = ResponseSchema(
        name="preparation_time",
        description="How much time in minutes do I need to prepare the recipe?\
                     Anwer with an integer number, or null if unknown",
        type="integer",
    )
    difficulty_schema = ResponseSchema(
        name="difficulty",
        description="How difficult is this recipe?\
                     Answer with one of these values: easy, normal, hard, very-hard"
    )
    ingredients_schema = ResponseSchema(
        name="ingredients",
        description="Give me a comma separated list of ingredients in lowercase or empty if unknown"
    )
    response_schemas = [cuisine_type_schema, preparation_time_schema, difficulty_schema, ingredients_schema]

    # get format instructions from responses
    output_parser = StructuredOutputParser.from_response_schemas(response_schemas)
    format_instructions = output_parser.get_format_instructions()
    
    analysis_template = """\
    Interprete and evaluate a recipe which title is: {title}
    and the description is: {description}
    
    {format_instructions}
    """
    prompt = ChatPromptTemplate.from_template(template=analysis_template)

    messages = prompt.format_messages(title=self.Recipe.Title, description=self.Recipe.Description, format_instructions=format_instructions)
    response = llm(messages)

    if debug:
        print("======ACTUAL PROMPT")
        print(messages[0].content)
        print("======RESPONSE")
        print(response.content)

    # populate analysis with results
    output_dict = output_parser.parse(response.content)
    self.CuisineType = output_dict['cuisine_type']
    self.Difficulty = output_dict['difficulty']
    self.Ingredients = output_dict['ingredients']
    if type(output_dict['preparation_time']) == int:
        self.PreparationTime = output_dict['preparation_time']

    return 1
}

}

O método "RunPythonAnalysis" é onde tudo relacionado a OpenAI acontece :). Você pode executá-lo diretamente no terminal para uma receita específica:

do ##class(yummy.analysis.SimpleOpenAI).%New(##class(yummy.data.Recipe).%OpenId(12)).RunPythonAnalysis(1)

Vamos obter uma saída assim:

USER>do ##class(yummy.analysis.SimpleOpenAI).%New(##class(yummy.data.Recipe).%OpenId(12)).RunPythonAnalysis(1)
======ACTUAL PROMPT
                    Interprete and evaluate a recipe which title is: Folded Sushi - Alaska Roll
                    and the description is: Craving for some sushi but don't have a sushi roller? Try this easy version instead. It's super easy yet equally delicious!
[Video Recipe](https://www.youtube.com/watch?v=1LJPS1lOHSM)
# Ingredients
Serving Size:  \~5 sandwiches      
* 1 cup of sushi rice
* 3/4 cups + 2 1/2 tbsp of water
* A small piece of konbu (kelp)
* 2 tbsp of rice vinegar
* 1 tbsp of sugar
* 1 tsp of salt
* 2 avocado
* 6 imitation crab sticks
* 2 tbsp of Japanese mayo
* 1/2 lb of salmon  
# Recipe     
* Place 1 cup of sushi rice into a mixing bowl and wash the rice at least 2 times or until the water becomes clear. Then transfer the rice into the rice cooker and add a small piece of kelp along with 3/4 cups plus 2 1/2 tbsp of water. Cook according to your rice cookers instruction.
* Combine 2 tbsp rice vinegar, 1 tbsp sugar, and 1 tsp salt in a medium bowl. Mix until everything is well combined.
* After the rice is cooked, remove the kelp and immediately scoop all the rice into the medium bowl with the vinegar and mix it well using the rice spatula. Make sure to use the cut motion to mix the rice to avoid mashing them. After thats done, cover it with a kitchen towel and let it cool down to room temperature.
* Cut the top of 1 avocado, then slice into the center of the avocado and rotate it along your knife. Then take each half of the avocado and twist. Afterward, take the side with the pit and carefully chop into the pit and twist to remove it. Then, using your hand, remove the peel. Repeat these steps with the other avocado. Dont forget to clean up your work station to give yourself more space. Then, place each half of the avocado facing down and thinly slice them. Once theyre sliced, slowly spread them out. Once thats done, set it aside.
* Remove the wrapper from each crab stick. Then, using your hand, peel the crab sticks vertically to get strings of crab sticks. Once all the crab sticks are peeled, rotate them sideways and chop them into small pieces, then place them in a bowl along with 2 tbsp of Japanese mayo and mix until everything is well mixed.
* Place a sharp knife at an angle and thinly slice against the grain. The thickness of the cut depends on your preference. Just make sure that all the pieces are similar in thickness.
* Grab a piece of seaweed wrap. Using a kitchen scissor, start cutting at the halfway point of seaweed wrap and cut until youre a little bit past the center of the piece. Rotate the piece vertically and start building. Dip your hand in some water to help with the sushi rice. Take a handful of sushi rice and spread it around the upper left hand quadrant of the seaweed wrap. Then carefully place a couple slices of salmon on the top right quadrant. Then place a couple slices of avocado on the bottom right quadrant. And finish it off with a couple of tsp of crab salad on the bottom left quadrant. Then, fold the top right quadrant into the bottom right quadrant, then continue by folding it into the bottom left quadrant. Well finish off the folding by folding the top left quadrant onto the rest of the sandwich. Afterward, place a piece of plastic wrap on top, cut it half, add a couple pieces of ginger and wasabi, and there you have it.
                    
                    A saída deve ser um fragmento de código markdown formatado no seguinte esquema, incluindo o "```json" e "```" à esquerda e à direita:
json
{
        "cuisine_type": string  // What is the cuisine type for the recipe?                                  Answer in 1 word max in lowercase
        "preparation_time": integer  // How much time in minutes do I need to prepare the recipe?                                    Anwer with an integer number, or null if unknown
        "difficulty": string  // How difficult is this recipe?                               Answer with one of these values: easy, normal, hard, very-hard
        "ingredients": string  // Give me a comma separated list of ingredients in lowercase or empty if unknown
}

                    
======RESPONSE
json
{
        "cuisine_type": "japanese",
        "preparation_time": 30,
        "difficulty": "easy",
        "ingredients": "sushi rice, water, konbu, rice vinegar, sugar, salt, avocado, imitation crab sticks, japanese mayo, salmon"
}

Tudo bem. Parece que nosso prompt da OpenAI é capaz de retornar algumas informações úteis. Vamos executar toda a classe da análise no terminal:

set a = ##class(yummy.analysis.SimpleOpenAI).%New(##class(yummy.data.Recipe).%OpenId(12))
do a.Run()
zwrite a
USER>zwrite a
a=37@yummy.analysis.SimpleOpenAI  ; <OREF>
+----------------- general information ---------------
|      oref value: 37
|      class name: yummy.analysis.SimpleOpenAI
| reference count: 2
+----------------- attribute values ------------------
|        CuisineType = "japanese"
|         Difficulty = "easy"
|        Ingredients = "sushi rice, water, konbu, rice vinegar, sugar, salt, avocado, imitation crab sticks, japanese mayo, salmon"
|    PreparationTime = 30
|             Reason = "It seems to be a japanese recipe!. You don't need too much time to prepare it"
|              Score = 3
+----------------- swizzled references ---------------
|           i%Recipe = ""
|           r%Recipe = "30@yummy.data.Recipe"
+-----------------------------------------------------

## Analisando todas as receitas! Naturalmente, você gostaria de executar a análise em todas as receitas que carregamos.

Você pode analisar uma variedade de IDs de receitas desta forma:

USER>do ##class(yummy.Utils).AnalyzeRange(1,10)
> Recipe 1 (1.755185s)
> Recipe 2 (2.559526s)
> Recipe 3 (1.556895s)
> Recipe 4 (1.720246s)
> Recipe 5 (1.689123s)
> Recipe 6 (2.404745s)
> Recipe 7 (1.538208s)
> Recipe 8 (1.33001s)
> Recipe 9 (1.49972s)
> Recipe 10 (1.425612s)

Depois disso, verifique novamente sua tabela de receitas e confira os resultados

select * from yummy_data.Recipe

image

Acho que eu poderia tentar a pizza de abóbora ou o tofu com kimchi coreano e porco :). Vou precisar conferir novamente em casa de qualquer forma :)

Observações finais

Encontre o exemplo completo em https://github.com/isc-afuentes/recipe-inspector

Com esse exemplo simples, aprendemos a usar as técnicas de LLM para adicionar recursos ou analisar partes dos seus dados no InterSystems IRIS.

Com esse ponto de partida, você pode pensar em:

  • Usar a BI do InterSystems para explorar e navegar pelos seus dados usando cubos e painéis.
  • Criar um webapp e fornecer IU (por exemplo, Angular). Para isso, você pode aproveitar pacotes como RESTForms2 para gerar automaticamente as APIs REST para suas classes persistentes.
  • Armazenar as receitas independentemente de gostar delas e, depois, tentar determinar se uma nova receita gostará de você? Você pode tentar uma abordagem com o IntegratedML ou até mesmo um LLM, fornecendo alguns dados de exemplo e criando um caso de uso de RAG (Geração Aumentada de Recuperação).

O que mais você pode tentar? Me diga o que você acha!

0
0 110
Artigo Danusa Calixto · jan 4, 2024 2m read

Você sabia que pode obter dados JSON diretamente das suas tabelas SQL?

Vou apresentar duas funções SQL úteis que são usadas para recuperar dados JSON de consultas SQL - JSON_ARRAY e JSON_OBJECT
Você pode usar essas funções na instrução SELECT com outros tipos de itens select, e elas podem ser especificadas em outros locais onde uma função SQL pode ser usada, como em uma cláusula WHERE 

A função JSON_ARRAY aceita uma lista separada por vírgula de expressões e retorna um array JSON com esses valores.

SELECT TOP 3Name,
JSON_ARRAY(%ID,%TABLENAME,UCASE(Name),Age,Home_State) "JSON data" 
FROM Sample.Person
Para  omitir propriedades de valores nulos, basta adicionar "ABSENT ON NULL" à função:
SELECT TOP 3Name,
JSON_ARRAY(%ID,%TABLENAME,UCASE(Name),Age,Home_State ABSENT ONNULL
) "JSON data" 
FROM Sample.Person

Para obter essas propriedades de valores nulos, use "NULL ON NULL" em vez disso (e, como isso é o padrão, você pode só não o adicionar como no primeiro exemplo).

Imagem obtendo todos os telefones de pacientes/clientes em um array JSON sem construi-lo​:

SELECT JSON_ARRAY(HomePhone,WorkPhone,Mobile) "JSON data"FROM Test.Phones
["055-8263371","052-4957286","054-4951066"]

A função JSON_OBJECT aceita uma lista separada por vírgulas de pares de chave:valor  e retorna um objeto JSON com esses valores.
Você pode especificar qualquer string entre aspas simples como um nome de chave, mas observe que isso não impõe nenhuma convenção de nomenclatura ou verificação de exclusividade para nomes de chaves.
Para o valor, você pode especificar um nome de coluna ou outra expressão. Além disso, observe que ele não aceita a sintaxe de asterisco (*) como uma forma de especificar todos os campos de uma tabela.

SELECT TOP 3 JSON_OBJECT('title':'Person from’,'country’:UCASE(Home_State),'table':%TABLENAME,'name':Name,'id':%ID,'age':Age) "JSON data" 
FROM Sample.Person

Para omitir as propriedades de valores nulos, basta adicionar "ABSENT ON NULL" à função:

SELECT TOP 3 JSON_OBJECT('title':'Person from’,'country’:UCASE(Home_State),'table':%TABLENAME,'name':Name,'id':%ID,'age':Age ABSENT ONNULL) "JSON data" 
FROM Sample.Person

Para obter essas propriedades de valores nulos, use "NULL ON NULL" em vez disso (e, como isso é o padrão, você pode só não o adicionar).

0
0 135
Artigo Davi Massaru Teixeira Muta · Nov. 26, 2023 9m read

Introdução

Este artigo tem como objetivo explorar como o sistema FHIR-PEX funciona e foi desenvolvido, aproveitando os recursos do InterSystems IRIS.

Agilizando a identificação e o processamento de exames médicos em centros de diagnóstico clínico, nosso sistema visa aumentar a eficiência e a precisão dos fluxos de trabalho de saúde. Ao integrar os padrões FHIR com o banco de dados Java-PEX da InterSystems IRIS, o sistema ajuda os profissionais de saúde com recursos de validação e roteamento, contribuindo, em última análise, para melhorar a tomada de decisões e o atendimento ao paciente.

como funciona

  • Interoperabilidade IRIS: Recebe mensagens no padrão FHIR, garantindo integração e compatibilidade com dados de saúde.

  • Processamento de informações com 'PEX Java': Processa mensagens no formato FHIR e as direciona para tópicos Kafka com base em regras configuradas globalmente no banco de dados, facilitando o processamento e roteamento eficiente de dados, principalmente para exames direcionados à quarentena.

  • Tratamento de devoluções Kafka via back-end Java externo: Interpreta apenas os exames direcionados à quarentena, permitindo que o sistema trate os retornos do Kafka por meio de um backend Java externo. Facilita a geração de insights prognósticos para profissionais de saúde através de IA Generativa, contando com consultas de resultados de exames anteriores dos respectivos pacientes.

 

Desenvolvimento

Através do PEX (Production EXtension) da InterSystems, ferramenta de extensibilidade que permite aprimoramento e customização do comportamento do sistema, elaboramos uma Operação de Negócio. Este componente tem a tarefa de processar mensagens recebidas no formato FHIR dentro do sistema.

Segue exemplo:

    import com.intersystems.enslib.pex.;     import com.intersystems.jdbc.IRISObject;     import com.intersystems.jdbc.IRIS;     import com.intersystems.jdbc.IRISList;     import com.intersystems.gateway.GatewayContext;          import org.apache.kafka.clients.producer.;     import org.apache.kafka.common.serialization.*;          import com.fasterxml.jackson.databind.JsonNode;     import com.fasterxml.jackson.databind.ObjectMapper;          import java.io.FileInputStream;     import java.io.IOException;     import java.util.Properties;

    public class KafkaOperation extends BusinessOperation {     // Connection to InterSystems IRIS     private IRIS iris;          // Connection to Kafka     private Producer<Long, String> producer;          // Kafka server address (comma separated if several)     public String SERVERS;          // Name of our Producer     public String CLIENTID;          /// Path to Config File     public String CONFIG;          public void OnInit() throws Exception {     [...]     }          public void OnTearDown() throws Exception {     [...]     }          public Object OnMessage(Object request) throws Exception {         IRISObject req = (IRISObject) request;         LOGINFO("Received object: " + req.invokeString("%ClassName", 1));              // Create record         String value = req.getString("Text");         String topic = getTopicPush(req);         final ProducerRecord<Long, String> record = new ProducerRecord<>(topic, value);              // Send new record         RecordMetadata metadata = producer.send(record).get();              // Return record info         IRISObject response = (IRISObject)(iris.classMethodObject("Ens.StringContainer","%New",topic+"|"+metadata.offset()));         return response;     }          private Producer<Long, String> createProducer() throws IOException {     [...]     }          private String getTopicPush(IRISObject req) {     [...]     }          [...]     } `

Dentro da aplicação, o método getTopicPush assume a responsabilidade de identificar o tópico para o qual a mensagem será enviada.

A determinação para qual tópico a mensagem será enviada depende da existência de uma regra na “quarantineRule” global, conforme lida dentro do IRIS.

    String code = FHIRcoding.path("code").asText();     String system = FHIRcoding.path("system").asText();

    IRISList quarantineRule = iris.getIRISList("quarantineRule",code,system);

     String reference = quarantineRule.getString(1);      String value = quarantineRule.getString(2);

     String observationValue = fhir.path("valueQuantity").path("value").asText()

Quando o ^quarantineRule global existe, a validação do objeto FHIR pode ser validada.

    private boolean quarantineValueQuantity(String reference, String value, String observationValue) {         LOGINFO("quarantine rule reference/value: " + reference + "/" + value);         double numericValue = Double.parseDouble(value);         double numericObservationValue = Double.parseDouble(observationValue);

        if ("<".equals(reference)) {             return numericObservationValue < numericValue;         }         else if (">".equals(reference)) {             return numericObservationValue > numericValue;         }         else if ("<=".equals(reference)) {             return numericObservationValue <= numericValue;         }         else if (">=".equals(reference)) {             return numericObservationValue >= numericValue;         }                  return false;     }

Exemplo prático:

Ao definir um global, como:

    Set ^quarantineRule("59462-2","http://loinc.org") = $LB(">","500") 

Isso estabelece uma regra para o código "59462-2" e o sistema ""http://loinc.org"" na ^quarantineRule global, especificando uma condição onde o valor quando maior que 500 é definido como quarentena. No aplicativo, o método getTopicPush pode então usar essa regra para determinar o tópico apropriado para enviar a mensagem com base no resultado da validação.

Dada a atribuição, o JSON abaixo seria enviado para quarentena, pois corresponde à condição especificada por ter:

 {
          "system": "http://loinc.org",
          "code": "59462-2",
          "display": "Testosterone"
}

"valueQuantity": { "value": 550, "unit": "ng/dL", "system": "http://unitsofmeasure.org", "code": "ng/dL" }

FHIR Observation:

{
    "resourceType": "Observation",
    "id": "3a8c7d54-1a2b-4c8f-b54a-3d2a7efc98c9",
    "status": "final",
    "category": [
      {
        "coding": [
          {
            "system": "http://terminology.hl7.org/CodeSystem/observation-category",
            "code": "laboratory",
            "display": "laboratory"
          }
        ]
      }
    ],
    "code": {
      "coding": [
        {
          "system": "http://loinc.org",
          "code": "59462-2",
          "display": "Testosterone"
        }
      ],
      "text": "Testosterone"
    },
    "subject": {
      "reference": "urn:uuid:274f5452-2a39-44c4-a7cb-f36de467762e"
    },
    "encounter": {
      "reference": "urn:uuid:100b4a8f-5c14-4192-a78f-7276abdc4bc3"
    },
    "effectiveDateTime": "2022-05-15T08:45:00+00:00",
    "issued": "2022-05-15T08:45:00.123+00:00",
    "valueQuantity": {
      "value": 550,
      "unit": "ng/dL",
      "system": "http://unitsofmeasure.org",
      "code": "ng/dL"
    }
}

### Quarkus Java application

Após o envio para o tópico desejado, foi construída uma aplicação Quarkus Java para recebimento de exames em quarentena.

    @ApplicationScoped      public class QuarentineObservationEventListener {

    @Inject     PatientService patientService;

    @Inject     EventBus eventBus;

    @Transactional     @Incoming("observation_quarantine")     public CompletionStage<Void> onIncomingMessage(Message<QuarentineObservation> quarentineObservationMessage) {         var quarentineObservation = quarentineObservationMessage.getPayload();         var patientId = quarentineObservation.getSubject()                 .getReference();         var patient = patientService.addObservation(patientId, quarentineObservation);         publishSockJsEvent(patient.getId(), quarentineObservation.getCode()                 .getText());         return quarentineObservationMessage.ack();     }

    private void publishSockJsEvent(Long patientId, String text) {         eventBus.publish("monitor", MonitorEventDto.builder()                 .id(patientId)                 .message(" is on quarentine list by observation ." + text)                 .build());     }      }

Este segmento do sistema tem a tarefa de persistir as informações recebidas de Kafka, armazená-las nas observações do paciente no banco de dados e notificar a ocorrência ao monitor.

O monitor

Por fim, o monitor do sistema é responsável por fornecer uma visualização simples do front-end. Isso permite que os profissionais de saúde revisem os dados do paciente/exame e tomem as ações necessárias.

Implementação of langchain

Através do monitor, o sistema permite que os profissionais de saúde solicitem recomendações da IA ​​Generativa.

    @Unremovable     @Slf4j     @ApplicationScoped     public class PatientRepository {         @Tool("Get anamnesis information for a given patient id")         public Patient getAnamenisis(Long patientId) {             log.info("getAnamenisis called with id " + patientId);             Patient patient = Patient.findById(patientId);             return patient;         }              @Tool("Get the last clinical results for a given patient id")         public List<Observation> getObservations(Long patientId) {             log.info("getObservations called with id " + patientId);             Patient patient = Patient.findById(patientId);             return patient.getObservationList();         }          }

segue implementação de langchain4j

    @RegisterAiService(chatMemoryProviderSupplier = RegisterAiService.BeanChatMemoryProviderSupplier.class, tools = {PatientRepository.class})     public interface PatientAI {              @SystemMessage("""                 You are a health care assistant AI. You have to recommend exams for patients based on history information.                 """)         @UserMessage("""                  Your task is to recommend clinical exams for the patient id {patientId}.                       To complete this task, perform the following actions:                  1 - Retrieve anamnesis information for patient id {patientId}.                  2 - Retrieve the last clinical results for patient id {patientId}, using the property 'name' as the name of exam and 'value' as the value.                  3 - Analyse results against well known conditions of health care.                       Answer with a single JSON document containing:                  - the patient id in the 'patientId' key                  - the patient weight in the 'weight' key                  - the exam recommendation list in the 'recommendations' key, with properties exam, reason and condition.                  - the 'explanation' key containing an explanation of your answer, especially about well known diseases.                      Your response must be just the raw JSON document, without json, or anything else.                  """)         String recommendExams(Long patientId);     }

Dessa forma, o sistema pode auxiliar os profissionais de saúde na tomada de decisões e na execução de ações.

Video demonstração 

VIDEO

Autores

NOTA: 

O aplicativo https://openexchange.intersystems.com/package/fhir-pex está participando atualmente do InterSystems Java Contest 2023. Sinta-se à vontade para explorar a solução e não hesite em entrar em contato se tiver alguma dúvida ou precisar de informações adicionais. Recomendamos executar o aplicativo em seu ambiente local para uma experiência prática. Obrigado pela oportunidade 😀!

Artigo original: https://community.intersystems.com/post/sending-kafka-messages-java-pex-processing-quarantine-exam-prognoses

0
0 147
Artigo Danusa Calixto · Ago. 21, 2023 3m read

Outro dia, vi um artigo sobre o uso do pacote %ZEN ao trabalhar com JSON e decidi escrever um artigo descrevendo uma abordagem mais moderna. Recentemente, houve uma grande mudança no uso de %ZEN.Auxiliary.* para as classes JSON dedicadas. Isso permitiu o trabalho mais orgânico com JSONs.

Portanto, há basicamente 3 classes principais para trabalhar com o JSON:

  • %Library.DynamicObject - oferece uma maneira simples e eficiente de encapsular e trabalhar com documentos JSON padrão. Além disso, há outra possibilidade além de escrever o código habitual para criar a instância de uma classe desta maneira
set obj = ##class(%Library.DynamicObject).%New()

É possível usar a seguinte sintaxe

set obj = {}
  • %Library.DynamicArray - oferece uma maneira simples e eficiente de encapsular e trabalhar com arrays JSON padrão. Com arrays, é possível usar a mesma abordagem com objetos, ou seja, você pode criar uma instância da classe
set array = ##class(%DynamicArray).%New()

Ou fazer isso usando colchetes []

set array = []
  • %JSON.Adaptor é uma maneira de mapear objetos do ObjectScript (registrado, serial ou persistente) para entidades dinâmicas ou texto JSON.
Vamos analisá-los um pouco mais a fundo.

Digamos que eu esteja trabalhando com um cliente RESTful e precise enviar algumas informações geradas a qualquer momento que não são um objeto do banco de dados, e sim algumas partes dele. Eu posso só criar uma nova instância de %DynamicObject e definir suas propriedades. De certa forma, é semelhante ao que foi feito anteriormente com o %ZEN.ProxyObject. E, é claro, posso ter objetos e arrays integrados como propriedades (ou campos JSON):

Set result={}
set result.Group = "TB-41"set result.Name = "Iryna Mykhailova"set result.Questions = ["What is JSON?", "Create instance of class Test and set all it's properties."]

Como resultado dessas linhas de código, vamos obter a seguinte string JSON:

{"Group":"TB-41","Name":"Iryna Mykhailova","Questions":["What is JSON?","Create instance of class Test and set all it's properties."]}

Além de definir as propriedades ou simplesmente escrever a string JSON dentro dos colchetes

Set result={"Group":"TB-41", "Name":"Iryna Mykhailova", "Questions":["What is JSON?", "Create instance of class Test and set all it's properties."]}
 

há a possibilidade de usar métodos para definir ( %Set() ), obter ( %Get() ) e excluir ( %Remove() ) os valores das propriedades. O mesmo vale para arrays.

E a última classe básica %JSON.Adaptor é usada como superclasse para ativar os recursos do JSON para as classes existentes. Portanto, se houver dados<font color="#000080"> </font>de classe usados no serviço RESTful, é fácil obter uma representação JSON usando o método %ToJSON()  e a ação oposta - %FromJSON(). Também há a possibilidade de serializar e desserializar as classes habilitadas para JSON para strings e streams, se necessário.

Isso conclui este breve tutorial sobre classes JSON e seus usos. Espero que isso ajude você a descobrir a melhor maneira de agir.

0
1 135