#Embedded Python

0 Seguidores · 58 Postagens

Embedded Python refere-se à integração da linguagem de programação Python no InterSystems IRIS kernel, o que permite que os desenvolvedores operem com dados e que desenvolvam lógicas de negócio para aplicativos no lado do servidor usando o Python.

Documentação.

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

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

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

0
0 22
Artigo Heloisa Paiva · Set. 30, 2025 3m read

Oi pessoal!  Esse artigo é para quem está começando com InterSystems IRIS. Espero que ajude!

O InterSystems IRIS é uma plataforma de dados unificada: uma base de dados de alta performance com ferramentas de interoperabilidade e análise integradas em um só produto. Você tem SQL e NoSQL na mesma máquina, além de jeitos nativos de rodar Python com seus dados. Em resumo: menos peças móveis, mais capacidade de processamento.

Por que engenheiros escolhem IRIS

0
0 28
Artigo Larissa Prussak · Ago. 29, 2025 1m read

Como parte de um projeto técnico recente de documentação para otimizar a busca, precisei usar Embedded Python no meu código ObjectScript.
O principal obstáculo foi passar uma lista do Python, criada em um método de classe Python, para um método ObjectScript.

Enviar a lista por referência para o método Python, preenchê-la com o método Insert(), e retornar a referência para o método ObjectScript resultava em uma lista do tipo %SYS.Python. Esse processo era simples, mas pouco eficiente.

0
0 21
Artigo Larissa Prussak · Jul. 24, 2025 1m read

Você está curioso para saber como executar scripts Python diretamente no terminal do InterSystems IRIS ou Caché? 🤔
Boa notícia: é fácil! 😆
O IRIS oferece suporte ao Embedded Python, permitindo que você use Python de forma interativa dentro do terminal do IRIS.

Como acessar o Shell do Python?

Para iniciar o shell do Python a partir do terminal do IRIS, basta executar o seguinte comando:

do##class(%SYS.Python).Shell()

Esse comando abre um shell interativo do Python dentro do terminal do IRIS. A partir daí, você pode escrever e executar código Python como faria em um ambiente Python normal.

0
0 25
Artigo Heloisa Paiva · Jun. 5, 2025 4m read

Duas Grandes Mudanças para a Ferramenta de Código Aberto TestCoverage: Suporte a Python Embutido e uma Nova Interface de Usuário

Python Embutido

Anteriormente, o TestCoverage conseguia rastrear a cobertura de testes unitários apenas para códigos escritos em ObjectScript. Ele ignorava o código escrito em outras linguagens, como Python, nas estatísticas de cobertura.

 

0
0 23
Artigo Heloisa Paiva · Jun. 4, 2025 9m read

1. Um Exemplo Motivador

O Python embarcado já existe há algum tempo. Você provavelmente seguiu os tutoriais e aprendeu sobre ele. No entanto, se você tentou combinar Python e ObjectScript em um trabalho de desenvolvimento real, provavelmente se deparou com situações em que recebeu uma mensagem de erro como esta:

USER>Do##class(MyClass).SomeMethod()

ERROR #5002: ObjectScript error: <PYTHON EXCEPTION> *<class 'ZeroDivisionError'>: division by zero

É uma string longa para informações limitadas. Tudo o que sabemos por essa mensagem é que ocorreu um erro de Python onde:

0
0 38
Artigo Heloisa Paiva · Abr. 18, 2025 18m read

Image generated by OpenAI DALL·E

Sou um grande fã de ficção científica, mas embora eu esteja totalmente a bordo da nave Star Wars (desculpas aos meus colegas Trekkies!), sempre apreciei os episódios clássicos de Star Trek da minha infância. A tripulação diversificada da USS Enterprise, cada um dominando suas funções únicas, é uma metáfora perfeita para entender os agentes de IA e seu poder em projetos como o Facilis. Então, vamos embarcar em uma missão intergaláctica, utilizando a IA como a tripulação da nossa nave e  audaciosamente ir audaciosamente ir homem jamais esteve!  Esse conceito de trabalho em equipe é uma analogia maravilhosa para ilustrar como os agentes de IA funcionam e como os usamos em nosso projeto DC-Facilis. Então, vamos mergulhar e assumir o papel de um capitão de nave estelar, liderando uma tripulação de IA em territórios inexplorados!

Bem-vindo ao CrewAI!

Para gerenciar nossa tripulação de IA, usamos uma estrutura fantástica chamada CrewAI.É enxuta, extremamente rápida e opera como uma plataforma Python multiagente. Uma das razões pelas quais a amamos, além do fato de ter sido criada por outro brasileiro, é sua incrível flexibilidade e design baseado em funções.

from crewai import Agent, Task, Crew

the taken quote

Conheça os Planejadores

No Facilis, nossos agentes de IA são divididos em dois grupos. Vamos começar com o primeiro, que gosto de chamar de "Os Planejadores".

O Agente de Extração

O papel principal do Facilis é receber uma descrição em linguagem natural de um serviço REST e criar automaticamente toda a interoperabilidade necessária. Portanto, nosso primeiro membro da tripulação é o Agente de Extração. Este agente tem a tarefa de "extrair" as especificações da API a partir da descrição fornecida pelo usuário.

Aqui está o que o Agente de Extração procura:

  • Host (obrigatório)
  • Endpoint (obrigatório)
  • Params (opcional)
  • Port (se disponível)
  • modelo JSON (para POST/PUT/PATCH/DELETE)
  • Autenticação (se aplicável)
    def create_extraction_agent(self) -> Agent:
        return Agent(
            role='Extrator de Especificações de API',
            goal='Extrair especificações de API de descrições em linguagem natural',
            backstory=dedent("""
                        Você é especializado em interpretar descrições em linguagem natural
                        e extrair especificações de API estruturadas.
            """),
            allow_delegation=True,
            llm=self.llm
        )

    def extract_api_specs(self, descriptions: List[str]) -> Task:
        return Task(
            description=dedent(f"""
               Extraia as especificações de API das seguintes descrições:
                {json.dumps(descriptions, indent=2)}
                
               Para cada descrição, extraia:
                - Host (obrigatório)
                - Endpoint (obrigatório)
                - Params (opcional)
                - Port (se disponível)
                - modelo JSON (para POST/PUT/PATCH/DELETE)
                - Autenticação (se aplicável)
                
                Marque quaisquer campos obrigatórios ausentes como 'missing'.
                Retorne os resultados em formato JSON como um array de especificações.
            """),
            expected_output="""Um array JSON contendo as especificações de API extraídas com todos os campos obrigatórios e opcionais""",
            agent=self.extraction_agent
        )

O Agente de Validação

Próximo na fila, o Agente de Validação! Sua missão é garantir que as especificações de API coletadas pelo Agente de Extração estejam corretas e consistentes. Ele verifica:

  1. Formato de host válido
  2. Endpoint começando com '/'
  3. Métodos HTTP válidos (GET, POST, PUT, DELETE, PATCH)
  4. Número de porta válido (se fornecido)
  5. Presença de modelo JSON para métodos aplicáveis.

    def create_validation_agent(self) -> Agent:
        return Agent(
            role='API Validator',
            goal='Validar especificações de API quanto à correção e consistência.',
            backstory=dedent("""
                 Você é um especialista em validação de API, garantindo que todas as especificações
                 atendam aos padrões e formatos necessários.
            """),
            allow_delegation=False,
            llm=self.llm
        )

 def validate_api_spec(self, extracted_data: Dict) -> Task:
        return Task(
            description=dedent(f"""
                Valide a seguinte especificação de API:
                {json.dumps(extracted_data, indent=2)}
                
                Verifique:
                1. Formato de host válido
                2. Endpoint começando com '/'
                3. Métodos HTTP válidos  (GET, POST, PUT, DELETE, PATCH)
                4. Número de porta válido (se fornecido)
                5. Presença de modelo JSON para métodos aplicáveis.
                
               Retorne os resultados da validação em formato JSON.
            """),
            expected_output="""Um objeto JSON contendo os resultados da validação com quaisquer erros ou confirmação de validade""",
            agent=self.validation_agent
        )

O Agente de Interação

Avançando, conhecemos o Agente de Interação, nosso Especialista em Interação com o Usuário. Seu papel é obter quaisquer campos de especificação de API ausentes que foram marcados pelo Agente de Extração e validá-los com base nas descobertas do Agente de Validação. Eles interagem diretamente com os usuários para preencher quaisquer lacunas.

O Agente de Produção

Precisamos de duas informações cruciais para criar a interoperabilidade necessária: namespace e nome da produção. O Agente de Produção interage com os usuários para coletar essas informações, de forma muito semelhante ao Agente de Interação.

O Agente de Transformação de Documentação

Assim que as especificações estiverem prontas, é hora de convertê-las em documentação OpenAPI. O Agente de Transformação de Documentação, um especialista em OpenAPI, cuida disso.

    def create_transformation_agent(self) -> Agent:
        return Agent(
            role='Especialista em Transformação OpenAPI',
            goal='Converter especificações de API em documentação OpenAPI',
            backstory=dedent("""
                Você é um especialista em especificações e documentação OpenAPI.
                Seu papel é transformar detalhes de API validados em documentação
                OpenAPI 3.0 precisa e abrangente.
            """),
            allow_delegation=False,
            llm=self.llm
        )

    def transform_to_openapi(self, validated_endpoints: List[Dict], production_info: Dict) -> Task:
        return Task(
            description=dedent(f"""
                Transforme as seguintes especificações de API validadas em documentação OpenAPI 3.0:
                
                Informações de Produção:
                {json.dumps(production_info, indent=2)}
                
               Endpoints Validados:
                {json.dumps(validated_endpoints, indent=2)}
                
               Requisitos:
               1. Gerar especificação OpenAPI 3.0 completa
               2. Incluir schemas de requisição/resposta apropriados
               3. Documentar todos os parâmetros e corpos de requisição
               4. Incluir autenticação se especificado
               5. Garantir formatação de caminho apropriada
                
                Retorne a especificação OpenAPI nos formatos JSON e YAML.
            """),
            expected_output="""Um objeto JSON contendo a especificação OpenAPI 3.0 completa com todos os endpoints e schemas.""",
            agent=self.transformation_agent
        )

The Review Agent

Após a transformação, a documentação OpenAPI passa por uma revisão meticulosa para garantir conformidade e qualidade. O Agente de Revisão segue esta lista de verificação:

1.Conformidade OpenAPI 3.0

  • Especificação de versão correta
  • Elementos raiz obrigatórios
  • Validação da estrutura do schema
  1. Completude
  • Todos os endpoints documentados
  • Parâmetros totalmente especificados
  • Schemas de requisição/resposta definidos
  • Esquemas de segurança configurados corretamente
  1. Verificações de Qualidade
  • Convenções de nomenclatura consistentes
  • Descrições claras
  • Uso adequado de tipos de dados
  • Códigos de resposta significativos
  1. Melhores Práticas
  • Uso adequado de tags
  • Nomenclatura de parâmetros consistente
  • Definições de segurança apropriadas

Finalmente, se tudo parecer bom, o Agente de Revisão reporta um objeto JSON saudável com a seguinte estrutura:

{
 "is_valid": boolean,
 "approved_spec": object (a especificação OpenAPI revisada e possivelmente corrigida),
 "issues": [array de strings descrevendo quaisquer problemas encontrados],
 "recommendations": [array de sugestões de melhoria]
}

    def create_reviewer_agent(self) -> Agent:
        return Agent(
            role='Revisor de Documentação OpenAPI',
            goal='Garantir a conformidade e qualidade da documentação OpenAPI',
            backstory=dedent("""
                Você é a autoridade final em qualidade e conformidade de documentação OpenAPI.
               Com vasta experiência em especificações OpenAPI 3.0, você revisa meticulosamente
               a documentação para precisão, completude e adesão aos padrões.
            """),
            allow_delegation=True,
            llm=self.llm
        )


    def review_openapi_spec(self, openapi_spec: Dict) -> Task:
        return Task(
            description=dedent(f"""
                Revise a seguinte especificação OpenAPI para conformidade e qualidade:
                
                {json.dumps(openapi_spec, indent=2)}
                
                Lista de Verificação da Revisão::
                1. Conformidade OpenAPI 3.0
                - Verificar a especificação de versão correta
                - Verificar os elementos raiz obrigatórios
                - Validar a estrutura do schema
                
                2. Completude
                - Todos os endpoints devidamente documentados
                - Parâmetros totalmente especificados
                - Schemas de requisição/resposta definidos
                - Esquemas de segurança configurados corretamente
                
                3. Quality Checks
                - Consistent naming conventions
                - Clear descriptions
                - Proper use of data types
                - Meaningful response codes
                
                4. Best Practices
                - Proper tag usage
                - Consistent parameter naming
                - Appropriate security definitions
                
                Você deve retornar um objeto JSON com a seguinte estrutura:
                {{
                    "is_valid": boolean,
                    "approved_spec": object (a especificação OpenAPI revisada e possivelmente corrigida),
                    "issues": [array de strings descrevendo quaisquer problemas encontrados],
                    "recommendations": [array de sugestões de melhoria]
                }}
            """),
            expected_output=""" Um objeto JSON contendo: is_valid (boolean), approved_spec (object), issues (array), e recommendations (array)""",
            agent=self.reviewer_agent
        )

O Agente Iris

O último agente no grupo do planejador é o Agente Iris, que envia a documentação OpenAPI finalizada para o Iris.


    def create_iris_i14y_agent(self) -> Agent:
        return Agent(
            role='Especialista em Integração Iris I14y',
            goal='Integrar especificações de API com o serviço Iris I14y',
            backstory=dedent("""
                  Você é responsável por garantir uma integração suave entre o sistema de
                 documentação da API e o serviço Iris I14y. Você lida com a
                 comunicação com o Iris, valida as respostas e garante a integração
                 bem-sucedida das especificações da API.
            """),
            allow_delegation=False,
            llm=self.llm
        )

    def send_to_iris(self, openapi_spec: Dict, production_info: Dict, review_result: Dict) -> Task:
        return Task(
            description=dedent(f"""
               Enviar a especificação OpenAPI aprovada para o serviço Iris I14y:

                Informações de Produção:
                - Nome: {production_info['production_name']}
                - Namespace: {production_info['namespace']}
                - É Novo: {production_info.get('create_new', False)}

               Status da Revisão:
                - Aprovado: {review_result['is_valid']}
                
                Retornar o resultado da integração em formato JSON.
            """),
            expected_output="""Um objeto JSON contendo o resultado da integração com o serviço Iris I14y, incluindo o status de sucesso e os detalhes da resposta.""",
            agent=self.iris_i14y_agent
        )

class IrisI14yService:
    def __init__(self):
        self.logger = logging.getLogger('facilis.IrisI14yService')
        self.base_url = os.getenv("FACILIS_URL", "http://dc-facilis-iris-1:52773") 
        self.headers = {
            "Content-Type": "application/json"
        }
        self.timeout = int(os.getenv("IRIS_TIMEOUT", "504"))  # in milliseconds
        self.max_retries = int(os.getenv("IRIS_MAX_RETRIES", "3"))
        self.logger.info("IrisI14yService initialized")

    async def send_to_iris_async(self, payload: Dict) -> Dict:
        """
        Enviar carga útil para o endpoint de geração do Iris de forma assíncrona.
        """
        self.logger.info("Enviando carga útil para o endpoint de geração do Iris.")
        if isinstance(payload, str):
            try:
                json.loads(payload)  
            except json.JSONDecodeError:
                raise ValueError("Invalid JSON string provided")
        
        retry_count = 0
        last_error = None

        # Cria timeout para o aiohttp
        timeout = aiohttp.ClientTimeout(total=self.timeout / 1000)  # Converte ms para seconds

        while retry_count < self.max_retries:
            try:
                self.logger.info(f"Attempt {retry_count + 1}/{self.max_retries}: Enviando requisição para {self.base_url}/facilis/api/generate")
                
                async with aiohttp.ClientSession(timeout=timeout) as session:
                    async with session.post(
                        f"{self.base_url}/facilis/api/generate",
                        json=payload,
                        headers=self.headers
                    ) as response:
                        if response.status == 200:
                            return await response.json()
                        response.raise_for_status()

            except asyncio.TimeoutError as e:
                retry_count += 1
                last_error = e
                error_msg = f"Timeout occurred (attempt {retry_count}/{self.max_retries})"
                self.logger.warning(error_msg)
                
                if retry_count < self.max_retries:
                    wait_time = 2 ** (retry_count - 1)
                    self.logger.info(f"Waiting {wait_time} seconds before retry...")
                    await asyncio.sleep(wait_time)
                continue

            except aiohttp.ClientError as e:
                error_msg = f"Failed to send to Iris: {str(e)}"
                self.logger.error(error_msg)
                raise IrisIntegrationError(error_msg)

        error_msg = f"Failed to send to Iris after {self.max_retries} attempts due to timeout"
        self.logger.error(error_msg)
        raise IrisIntegrationError(error_msg, last_error)

Conheça os Geradores

Nosso segundo conjunto de agentes são os Geradores. Eles estão aqui para transformar as especificações OpenAPI em interoperabilidade InterSystems IRIS. Há oito deles neste grupo.

O primeiro deles é o Agente Analisador. Ele é como o planejador, traçando a rota. Seu trabalho é mergulhar nas especificações OpenAPI e descobrir quais componentes de Interoperabilidade IRIS são necessários.


    def create_analyzer_agent():
        return Agent(
            role="Analisador de Especificações OpenAPI",
            goal="Analisar minuciosamente as especificações OpenAPI e planejar os componentes de Interoperabilidade IRIS",
            backstory="""Você é um especialista em especificações OpenAPI e em Interoperabilidade InterSystems IRIS.
                     Seu trabalho é analisar documentos OpenAPI e criar um plano detalhado de como eles devem ser implementados como componentes de Interoperabilidade IRIS.""",
            verbose=False,
            allow_delegation=False,
            tools=[analyze_openapi_tool],
            llm=get_facilis_llm()
        )

   analysis_task = Task(
        description="""Analisar a especificação OpenAPI e planejar os componentes de Interoperabilidade IRIS necessários.
Incluir uma lista de todos os componentes que devem estar na classe de Produção."",
        agent=analyzer,
        expected_output="Uma análise detalhada da especificação OpenAPI e um plano para os componentes IRIS, incluindo a lista de componentes de Produção",
        input={
            "openapi_spec": openApiSpec,
            "production_name": "${production_name}" 
        }
    )

Em seguida, os Agentes de Business Services (BS) e Business Operations (BO) assumem o controle. Eles geram os Business Services e as Business Operations com base nos endpoints OpenAPI. Eles usam uma ferramenta útil chamada MessageClassTool para gerar as classes de mensagens perfeitas, garantindo a comunicação.


    def create_bs_generator_agent():
        return Agent(
            role="Gerador de Produção e Business Service IRIS",
            goal="Gerar classes de Produção e Business Service IRIS formatadas corretamente a partir de especificações OpenAPI",
            backstory="""Você é um desenvolvedor InterSystems IRIS experiente, especializado em Produções de Interoperabilidade.
                 Sua expertise reside na criação de Business Services e Produções capazes de receber e processar requisições de entrada com base emespecificações de API."",
            verbose=False,
            allow_delegation=True,
            tools=[generate_production_class_tool, generate_business_service_tool],
            llm=get_facilis_llm()
        )

    def create_bo_generator_agent():
        return Agent(
            role="Gerador de Business Operation IRIS",
            goal="Gerar classes de Business Operation IRIS formatadas corretamente a partir de especificações OpenAPI",
            backstory="""Você é um desenvolvedor InterSystems IRIS experiente, especializado em Produções de Interoperabilidade.
                 Sua expertise reside na criação de Business Operations capazes de enviar requisições para sistemas externos com base em especificações de API.""",
            verbose=False,
            allow_delegation=True,
            tools=[generate_business_operation_tool, generate_message_class_tool],
            llm=get_facilis_llm()
        )

    bs_generation_task = Task(
        description="Gerar classes de Business Service com base nos endpoints OpenAPI",
        agent=bs_generator,
        expected_output="Definições de classes de Business Service do IRIS",
        context=[analysis_task]
    )

    bo_generation_task = Task(
        description="Gerar classes de Business Operation com base nos endpoints OpenAPI",
        agent=bo_generator,
        expected_output="Definições de classes de Business Operation do IRIS",
        context=[analysis_task]
    )

    class GenerateMessageClassTool(BaseTool):
        name: str = "generate_message_class"
        description: str = "Gerar uma classe de Mensagem IRIS"
        input_schema: Type[BaseModel] = GenerateMessageClassToolInput

        def _run(self, message_name: str, schema_info: Union[str, Dict[str, Any]]) -> str:
            writer = IRISClassWriter()
            try:
                if isinstance(schema_info, str):
                    try:
                        schema_dict = json.loads(schema_info)
                    except json.JSONDecodeError:
                        return "Error: Invalid JSON format for schema info"
                else:
                    schema_dict = schema_info

                class_content = writer.write_message_class(message_name, schema_dict)
                # Armazenar a classe gerada.
                writer.generated_classes[f"MSG.{message_name}"] = class_content
                return class_content
            except Exception as e:
                return f"Error generating message class: {str(e)}"

Depois que BS e BO fazem o que têm que fazer, é a hora do Agente de Produção brilhar! Este agente junta tudo para criar um ambiente de produção coeso.

Depois que tudo estiver configurado, o próximo na linha é o Agente de Validação. Este entra em cena para uma verificação final, garantindo que cada classe Iris esteja ok.

Em seguida, temos o Agente de Exportação e o Agente de Coleção. O Agente de Exportação gera os arquivos .cls, enquanto o Agente de Coleção reúne todos os nomes de arquivos. Tudo é passado para o importador, que compila tudo no InterSystems Iris.


    def create_exporter_agent():
        return Agent(
            role="Exportador de Classes IRIS",
            goal="Exportar e validar definições de classes IRIS para arquivos .cls adequados",
            backstory="""Você é um especialista em implantação InterSystems IRIS. Seu trabalho é garantir que as definições de classes IRIS geradas sejam devidamente exportadas como arquivos .cls válidos que
                possam ser importados diretamente para um ambiente IRIS.""",
            verbose=False,
            allow_delegation=False,
            tools=[export_iris_classes_tool, validate_iris_classes_tool],
            llm=get_facilis_llm()
        )
        
    def create_collector_agent():
        return Agent(
            role="Coletor de Classes IRIS",
            goal="Coletar todos os arquivos de classes IRIS gerados em uma coleção JSON",
            backstory="""Você é um especialista em sistema de arquivos responsável por reunir e
                organizar os arquivos de classes IRIS gerados em uma coleção estruturada.""",
            verbose=False,
            allow_delegation=False,
            tools=[CollectGeneratedFilesTool()],
            llm=get_facilis_llm()
        )

    export_task = Task(
        description="Exportar todas as classes IRIS geradas como arquivos .cls válidos",
        agent=exporter,
        expected_output="Arquivos .cls IRIS válidos salvos no diretório de saída",
        context=[bs_generation_task, bo_generation_task],
        input={
            "output_dir": "/home/irisowner/dev/output/iris_classes"  # Optional
        }
    )

    collection_task = Task(
        description="Coletar todos os arquivos de classes IRIS gerados em uma coleção JSON",
        agent=collector,
        expected_output="Coleção JSON de todos os arquivos .cls gerados",
        context=[export_task, validate_task],
        input={
            "directory": "./output/iris_classes"
        }
    )

Limitações e Desafios

Nosso projeto começou como um experimento empolgante, onde meus colegas mosqueteiros e eu almejávamos criar uma ferramenta totalmente automatizada usando agentes. Foi uma jornada selvagem! Nosso foco principal estava em integrações de API REST. É sempre uma alegria receber uma tarefa com uma especificação OpenAPI para integrar; no entanto, sistemas legados podem ser uma história completamente diferente. Pensamos que automatizar essas tarefas poderia ser incrivelmente útil. Mas toda aventura tem suas reviravoltas: Um dos maiores desafios foi instruir a IA a converter OpenAPI para Interoperabilidade Iris. Começamos com o modelo openAI GPT3.5-turbo, que em testes iniciais se mostrou difícil com depuração e prevenção de interrupções. A mudança para o Anthropic Claude 3.7 Sonnet mostrou melhores resultados para o grupo Gerador, mas não tanto para os Planejadores... Isso nos levou a dividir nossas configurações de ambiente, usando diferentes provedores de LLM para flexibilidade. Usamos GPT3.5-turbo para planejamento e Claude sonnet para geração, uma ótima combinação! Essa combinação funcionou bem, mas encontramos problemas com alucinações. A mudança para o GT4o melhorou os resultados, mas ainda enfrentamos alucinações na criação de classes Iris e, às vezes, especificações OpenAPI desnecessárias, como o renomado exemplo Pet Store OpenAPI. Nos divertimos muito aprendendo ao longo do caminho, e estou super animado com o futuro incrível nesta área, com inúmeras possibilidades!

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

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

Introdução

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

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

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

Destaques do Lançamento

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

0
0 51
InterSystems Oficial Danusa Calixto · Mar. 26, 2025 5m read

A interface de usuário de interoperabilidade agora inclui experiências de usuário modernizadas para os aplicativos Editor DTL e Configuração da Produção que estão disponíveis para aceitação em todos os produtos de interoperabilidade. Você pode alternar entre as visualizações modernizada e padrão. Todas as outras telas de interoperabilidade permanecem na interface de usuário padrão. Observe que as alterações são limitadas a esses dois aplicativos e identificamos abaixo a funcionalidade que está disponível atualmente.

0
0 38
Artigo Julio Esquerdo · Nov. 8, 2024 4m read

Usando o Python no InterSystems IRIS

Vamos neste breve artigo ver como podemos utilizar o python como linguagem de programação dentro o InterSystems IRIS. Para o nosso exemplo vamos criar um método que exporta os dados de uma tabela do IRIS para um arquivo no formato XLS (MS-Excel). Para isso vamos utilizar a biblioteca pandas do python.

Primeiro, vamos ver a nossa tabela.:

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

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

Demonstração do aplicativo

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

Armazenamento de imagens

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

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

Olá Comunidade,

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

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

0
0 34
Artigo Heloisa Paiva · jan 26, 2025 8m read

No artigo anterior. Práticas de membros de classe e sua execução dentro do Python embutido. Agora voltaremos nossa atenção para o processo de alternância de espaços de nomes, acesso a variáveis globais, travessia e execução de rotinas dentro do Python embutido.

Antes de prosseguir para as outras funções. vamos revisar brevemente a função executedentro do pacote iris. Esta função é excepcionalmente benéfica para executar funções ObjectScript arbitrárias e invocação de classe.

0
0 33
Artigo Heloisa Paiva · jan 23, 2025 7m read

Olá comunidade,

Neste artigo, vou descrever e ilustrar o processo de implementação do ObjectScript dentro do Python embutido. Esta discussão também fará referência a outros artigos relacionados ao Python embutido, bem como abordará questões que foram benéficas para a minha jornada de aprendizado.

Como você sabe, a integração de recursos Python dentro do IRIS tem sido possível há algum tempo. Este artigo se concentrará em como incorporar perfeitamente o ObjectScript com o Python embutido.

0
0 41
Artigo Heloisa Paiva · jan 16, 2025 5m read

Tenho o prazer de anunciar a nova versão do IoP, que aliás não é apenas uma linha de comando. Estou dizendo isso porque o novo mecanismo de pesquisa de IA ainda pensa que o IoP é apenas uma linha de comando. Mas não é. É uma estrutura completa para construir aplicativos sobre a estrutura de interoperabilidade do IRIS com uma abordagem priorizando Python.

A nova versão do IoP: 3.2.0 possui muitas novidades, mas a mais importante é o suporte a DTL (Data Type Language). 🥳

Tanto para mensagens IoP quanto para jsonschema. 🎉

image

Suporte DTL

A partir da versão 3.2.0, o IoP oferece suporte a transformações DTL.

DTL é a camada de transformação de dados na Interoperabilidade do IRIS.

As transformações DTL são usadas para transformar dados de um formato para outro usando um editor gráfico. Também oferece suporte a estruturas jsonschema.

Como usar DTL com Mensagens

Primeiramente, você precisa registrar sua classe de mensagem em um arquivo settings.py.

Para fazer isso, adicione a seguinte linha no arquivo settings.py :

settings.py

from msg import MyMessage

SCHEMAS = [MyMessage]

A seguir, você pode usar o comando de migração do IoP para gerar arquivos de esquema para suas classes de mensagem.

iop --migrate /path/to/your/project/settings.py

Exemplo

msg.py

from iop import Message
from dataclasses import dataclass

@dataclass
class MyMessage(Message):
    name: str = None
    age: int = None

settings.py

from msg import MyMessage

SCHEMAS = [MyMessage]

Migrar os arquivos do esquema.

iop --migrate /path/to/your/project/settings.py

Construindo uma Transformação DTL

Para construir uma transformação DTL, você precisa criar uma nova classe de transformação DTL.

Vá para o Portal de Gerenciamento de Interoperabilidade do IRIS e crie uma nova transformação DTL.

image

Em seguida, selecione as classes de mensagem de origem e destino.

image

E seu esquema.

image

Então você pode começar a construir sua transformação.

image

Você também pode testar sua transformação.

image

Exemplo de carga útil para testar como mensagem de origem:

<test>
  <Message>
    <json><![CDATA[
{
"list_str":["toto","titi"],
"post":{"Title":"foo","Selftext":"baz"},
"list_post":[{"Title":"bar","Selftext":"baz"},{"Title":"foo","Selftext":"foo"}]
}
]]></json>
  </Message>
</test>

Suporte JsonSchema

A partir da versão 3.2.0, o IoP suporta estruturas jsonschema para transformações DTL.

Assim como para classes de mensagens, você precisa registrar seu jsonschema.

Para fazer isso, você precisa invocar seu comando iris:

zw ##class(IOP.Message.JSONSchema).ImportFromFile("/irisdev/app/random_jsonschema.json","Demo","Demo")

Onde o primeiro argumento é o caminho para o arquivo jsonschema, o segundo argumento é o nome do pacote e o terceiro argumento é o nome do esquema.

Então você pode usá-lo em sua transformação DTL.

O esquema estará disponível com o nome de Demo.

Exemplo de arquivo jsonschema:

{
    "$schema": "https://json-schema.org/draft/2020-12/schema",
    "type": "object",
    "title": "PostMessage",
    "properties": {
        "post": {
            "allOf": [
                {
                    "$ref": "#/$defs/PostClass"
                }
            ]
        },
        "to_email_address": {
            "type": "string",
            "default": null
        },
        "my_list": {
            "type": "array",
            "items": {
                "type": "string"
            }
        },
        "found": {
            "type": "string",
            "default": null
        },
        "list_of_post": {
            "type": "array",
            "items": {
                "allOf": [
                    {
                        "$ref": "#/$defs/PostClass"
                    }
                ]
            }
        }
    },
    "$defs": {
        "PostClass": {
            "type": "object",
            "title": "PostClass",
            "properties": {
                "title": {
                    "type": "string"
                },
                "selftext": {
                    "type": "string"
                },
                "author": {
                    "type": "string"
                },
                "url": {
                    "type": "string"
                },
                "created_utc": {
                    "type": "number"
                },
                "original_json": {
                    "type": "string",
                    "default": null
                }
            },
            "required": [
                "title",
                "selftext",
                "author",
                "url",
                "created_utc"
            ]
        }
    }
}

Exemplo de Transformação DTL com JsonSchema ou Classe de Mensagem

Muitos podem ser encontrados no pacote UnitTest no diretório./src/tests/cls.

Class UnitTest.ComplexTransform Extends Ens.DataTransformDTL [ DependsOn = IOP.Message ]
{

Parameter IGNOREMISSINGSOURCE = 1;

Parameter REPORTERRORS = 1;

Parameter TREATEMPTYREPEATINGFIELDASNULL = 0;

XData DTL [ XMLNamespace = "http://www.intersystems.com/dtl" ]
{
<transform sourceClass='IOP.Message' targetClass='IOP.Message' sourceDocType='registerFilesIop.message.ComplexMessage' targetDocType='registerFilesIop.message.ComplexMessage' create='new' language='objectscript' >
<assign value='source.{post}' property='target.{post}' action='set' />
<foreach property='source.{list_str()}' key='k1' >
<assign value='source.{list_str(k1)}_"foo"' property='target.{list_str()}' action='append' />
</foreach>
<foreach property='source.{list_post()}' key='k2' >
<assign value='source.{list_post().Title}' property='target.{list_post(k2).Title}' action='append' />
</foreach>
</transform>
}

}

Nova documentação

O IoP conta com uma nova documentação, disponível em https://grongierisc.github.io/interoperability-embedded-python/.

Você encontrará todas as informações necessárias para começar a usar o IoP.

image

Espero que você goste desta nova versão do IoP. 🎉

0
0 43
Artigo Davi Massaru Teixeira Muta · Nov. 5, 2024 13m read

Utilizando IRIS - Vector Search

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

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

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

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

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

Por que o Vector Search ?

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

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

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

DATA SET

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

Criação da tabela.

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

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

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

Para isso, podemos rodar o sql:

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

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

Class dc.filmes Extends %Persistent
{

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

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

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

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

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

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

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

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

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

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

VETORIZANDO

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


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

Armazenado Vector com InterSystems IRIS

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

Class dc.util [ Language = python ]
{

ClassMethod PopularFilmes()
{
    import pandas as pd

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

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

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

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

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

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

}

Observação:

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

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

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

str(row['overview_vector'])

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

Consultando Registros Similares

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

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

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

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

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

Exemplo da consulta script python:

import iris
from sentence_transformers import SentenceTransformer

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

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

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

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

Codificando com flask e embedded python

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

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

import iris

app = Flask(__name__)

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

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

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

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

Resultado Final:

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

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

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

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

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

Aproveite!

image

7
3 202
Artigo Heloisa Paiva · Out. 16, 2024 2m read

Olá Comunidade,

Este artigo tem como objetivo guiá-lo pelo processo de configuração e utilização do recurso Python Runtime Flexível para Python embutido. Antes da versão 2024.2, o instalador do InterSystems IRIS incluía uma versão pré-instalada do Python. Você pode encontrar as bibliotecas Python e os arquivos de aplicação localizados no diretório \lib\python dentro da sua pasta de instalação do IRIS (por exemplo, C:\InterSystems\IRIS20242\lib\python).

0
0 34
Artigo Heloisa Paiva · Set. 4, 2024 7m read

Como parte do concurso IRIS Python 2024, meu colega Damir e eu tivemos uma ideia de onstruir uma plataforma chamada ShelterShare para conectar vítimas e voluntários para requisições de abrigo. Para isso, escolhemos Django como uma framework e procedemos para construir a primeira versão ccom 3 docker containers diferentes, django, iris e nginx, que iriam então utilizar o IRIS puramente como uma máquina de base de dados pelo muito bem composto django_iris (cumprimentos ao Dimitry). Como progredimos rápido, decidimos explorar a opção de rodar ele dentro do mesmo container que o IRIS utilizando o

0
0 50
Artigo Heloisa Paiva · Ago. 27, 2024 7m read

Tenho orgulho de anunciar o novo lançamento de iris-pex-embedded-python (v2.3.1) com uma nova interface de linha de comando.

Essa linha de comando é chamada iop, de Interoperability On Python.

Primeiro, eu gostaria de apresentar em algumas palavras as maiores mudanças no projeto desde a primeira versão.

Um breve histórico do projeto

A versão 1.0 foi uma prova de conceito para mostrar como a framework de interoperabilidade do IRIS pode ser usada com uma abordagem primeiro python enquanto permanece compatível com qualquer código ObjectScript existente.

O que isso significa? Significa que qualquer desenvolvedor python pode usar a framework de interoperabilidade do IRIS sem ter nenhum conhecimento de ObjectScript.

Exemplo:

from grongier.pex import BusinessOperation

class MyBusinessOperation(BusinessOperation):

    def on_message(self, request):
        self.log.info("Received request")

Incrível, não é?

Com a versão 1.1, eu adicionei a possibilidade de registrar as classes python para o IRIS com uma função ajudante.

from grongier.pex import Utils

Utils.register_file("/src/MyBusinessOperation.py")

A versão 2.0 foi um lançamento maior porque agora você pode instalar o projeto com pip.

pip install iris-pex-embedded-python

O que há de novo na versão 2.3.1

A versão 2.3.1 é um lançamento grande porque introduz uma nova interface de linha de comando

Essa interface de linha de comando pode ser usada com esse projeto python baseada neste módulo ou talvez projetos que não usem este módulo.

Deixe-me introduzi-lo e explicar porque pode ser usado em projetos sem python.

a interface de linha de comando

A linha de comando é parte deste projeto, para instalá-la você deve instalar o projeto com pip.

pip install iris-pex-embedded-python

Então você pode usar a linha de comando iop para iniciar a framework de interoperabilidade.

iop

saída:

usage: iop [-h] [-d DEFAULT] [-l] [-s START] [-k] [-S] [-r] [-M MIGRATE] [-e EXPORT] [-x] [-v] [-L]
optional arguments:
  -h, --help            display help and default production name
  -d DEFAULT, --default DEFAULT
                        set the default production
  -l, --lists           list productions
  -s START, --start START
                        start a production
  -k, --kill            kill a production (force stop)
  -S, --stop            stop a production
  -r, --restart         restart a production
  -M MIGRATE, --migrate MIGRATE
                        migrate production and classes with settings file
  -e EXPORT, --export EXPORT
                        export a production
  -x, --status          status a production
  -v, --version         display version
  -L, --log             display log

default production: UnitTest.Production

Vamos ver alguns exemplos.

help

O comando help exibe a ajuda e o nome padrão da produção.

iop -h

Saída:

usage: python3 -m grongier.pex [-h] [-d DEFAULT] [-l] [-s START] [-k] [-S] [-r] [-M MIGRATE] [-e EXPORT] [-x] [-v] [-L]
...
default production: PEX.Production

default

O comando default define a produção padrão.

Sem argumento, ele exibe a produção default.

iop -d

output :

default production: PEX.Production

Com um argumento, ele define a produção padrão.

iop -d PEX.Production

lists

O comando lists lista as produções.

iop -l

Saída:

{
    "PEX.Production": {
        "Status": "Stopped",
        "LastStartTime": "2023-05-31 11:13:51.000",
        "LastStopTime": "2023-05-31 11:13:54.153",
        "AutoStart": 0
    }
}

start

O comando start inicia uma produção

Para sair do comando, você deve apertar CTRL+C.

iop -s PEX.Production

Se nenhum argumento for dado, o comando start inicia a produção padrão.

iop -s

Saída:

2021-08-30 15:13:51.000 [PEX.Production] INFO: Starting production
2021-08-30 15:13:51.000 [PEX.Production] INFO: Starting item Python.FileOperation
2021-08-30 15:13:51.000 [PEX.Production] INFO: Starting item Python.EmailOperation
...

kill

O comando kill mata uma produção (força parada).

O comando kill é o mesmo que o de parada (stop), mas com um "forçar" (force) na frente.

O comando kill não leva argumento porque só pode ter uma produção rodando.

iop -k 

stop

O comando stop para uma produção.

O comando stop não tem argumentos porque só pode ter uma produção rodando

iop -S 

restart

O comando restart reinicia uma produção.

O comando restart não tem argumentos porque só pode ter uma produção rodando.

iop -r 

migrate

O comando migrate migra uma produção e classes com arquivo de definições settings.

O comando migrate deve ter como argumento o caminho completo do arquivo de definições settings.

O arquivo de definições settings deve estar na mesma pasta do código python.

iop -M /tmp/settings.py

export

O comando export exporta uma produção.

Se não for dado nenhum argumento, o comando export exporta a produção padrão.

iop -e

Se um argumento for dado, o comando export exporta a produção no dado argumento.

iop -e PEX.Production

output :

{
    "Production": {
        "@Name": "PEX.Production",
        "@TestingEnabled": "true",
        "@LogGeneralTraceEvents": "false",
        "Description": "",
        "ActorPoolSize": "2",
        "Item": [
            {
                "@Name": "Python.FileOperation",
                "@Category": "",
                "@ClassName": "Python.FileOperation",
                "@PoolSize": "1",
                "@Enabled": "true",
                "@Foreground": "false",
                "@Comment": "",
                "@LogTraceEvents": "true",
                "@Schedule": "",
                "Setting": [
                    {
                        "@Target": "Adapter",
                        "@Name": "Charset",
                        "#text": "utf-8"
                    },
                    {
                        "@Target": "Adapter",
                        "@Name": "FilePath",
                        "#text": "/irisdev/app/output/"
                    },
                    {
                        "@Target": "Host",
                        "@Name": "%settings",
                        "#text": "path=/irisdev/app/output/"
                    }
                ]
            }
        ]
    }
}

status

O comando status dá o status de uma produção.

O comando status não leva argumentos pois apenas uma produção pode estar rodando.

iop -x 

output :

{
    "Production": "PEX.Production",
    "Status": "stopped"
}

Os status podem ser:

  • stopped (parada)
  • running (rodando)
  • suspended (suspensa)
  • troubled (com problema)

version

O comando version exibe a versão.

iop -v

output :

2.3.0

log

O comando log exibe o log.

Para sair do comando você deve apertar CTRL+C

iop -L

output :

2021-08-30 15:13:51.000 [PEX.Production] INFO: Starting production
2021-08-30 15:13:51.000 [PEX.Production] INFO: Starting item Python.FileOperation
2021-08-30 15:13:51.000 [PEX.Production] INFO: Starting item Python.EmailOperation
...

Ele pode ser usado fora do projeto iris-pex-embedded-python?

Isso será uma escolha sua.

Mas, antes de você sair daqui, deixe eu te dizer porque eu acho que pode ser usado fora de um projeto iris-pex-embedded-python.

Primeiro, porque ele pode interagir com a produção sem a necessidade de usar um terminal iris. Isso significa que é mais fácil de usar em um script.

Segundo, porque o settings.py pode ser usado para importar uma produção e classes com variáveis de ambiente.

Aqui está um exemplo de settings.py:

import os

PRODUCTIONS = [
        {
            'UnitTest.Production': {
                "Item": [
                    {
                        "@Name": "Python.FileOperation",
                        "@ClassName": "Python.FileOperation",
                        "Setting": {
                            "@Target": "Host",
                            "@Name": "%settings",
                            "#text": os.environ['SETTINGS']
                        }
                    }
                ]
            }
        } 
    ]

Note o valor #text. É um variável de ambiente. Bacana, né?

Você se vê usando essa ferramenta de linha de comando, o suficiente para valer a pena continuar desenvolvendo?

Obrigado por ler e seus feedbacks são bem vindos.

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

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

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

0
0 53
Artigo Heloisa Paiva · Jul. 18, 2024 3m read

Introdução ao WSGI em IRIS

Com o IRIS 2024+, os usuários podem hospedar aplicações WSGI usando Security.Applications. Por exemplo, um usuário pode fazer algo como o seguinte:

Exemplo funcional mínimo

zn "%SYS"
Kill props
Set props("Description") = "Sample WSGI Application"
Set props("MatchRoles") = ":%All"
Set props("WSGIAppLocation") = "/path/to/flaskapp"
Set props("WSGIAppName") = "myapp"
Set props("WSGICallable") = "app"
Set props("DispatchClass") = "%SYS.Python.WSGI" // importante, se não será reconhecido como uma aplicação CSP
Set sc = ##class(Security.Applications).Create("/flask", .props)
zw sc

onde o diretório /path/to/flaskapp contém um arquivo myapp.py que lê

from flask import Flask

app = Flask(__name__)

@app.route("/")
def index():
    return "Olá, WSGI!"

Agora, vá para a URL http(s)://<host>:<port>/<optional-prefix>/flask/. Ela deve mostrar "Olá, WSGI!" em texto padrão.

Armadilhas comuns

  1. Se a URL http(s):///flask/ não estiver funcionando, verifique a barra no final, que deve estar presente.

  2. Além disso, ao rodar pela primeira vez, flask deve estar instalado installed para o python embutido (não seu interpretador local a nível de SO - sistema operacional). Verifique se a instalação teve sucesso entrando no terminal de comando de python embutido e rodando import flask.

  3. Finalmente, a permissão de leitura de qualquer usuário de SO que o IRIS assuma deve ser garantida ao caminho /path/to/flaskapp/myapp.py e todas as pastas pai.

  4. Se o erro ainda não for resolvido, verifique as entradas em messages.log. Você também pode entrar em contato conosco postando um issue

Usando IPM para enviar aplicações WSGI para fácil instalação

O IPM faz esse processo mais fácil ao

  1. copiar o diretório flask app para um caminho com acesso de leitura garantido
  2. instalar dependências python relecantes em um arquivo requirements.txt

Exemplo de pacote

Aqui está um exemplo que pode ser instalado facilmente em qualquer IPM (v0.6.3+) instalado em IRIS 2024+. Clone esse pacote para um <PACKAGE_ROOT> adequado e inicie um terminal IRIS.

zn "%SYS"
zpm "load <PACKAGE_ROOT>"

Após instalação bem sucedida, você deve poder visitar http(s)://<host>:<port>/<optional-instance-prefix>/my/flask/demo/. No meu caso, a URL é http://localhost:8080/iris-ml-wsgi/my/flask/demo/ e lê-se:

This is a sample WSGI application using Flask!

Dica: Você precisa instalar zpm seguindo as instruções aqui primeiro, para que o comando zpm funcione.

O module.xml do repositório acima também está listado aqui para rápida referência

<?xml version="1.0" encoding="UTF-8"?>
<Export generator="Cache" version="25">
  <Document name="flask-demo.ZPM">
    <Module>
      <Name>flask-demo</Name>
      <Version>1.0.0</Version>
      <Description>This is a demo of a flask application</Description>
      <Keywords>flask</Keywords>
      <Author>
        <Person>Shuheng Liu</Person>
        <Organization>InterSystems</Organization>
        <CopyrightDate>2024</CopyrightDate>
        <License>MIT</License>
        <Notes>notes</Notes>
      </Author>
      <Packaging>module</Packaging>
      <SystemRequirements Version=">=2024.1" />
      <SourcesRoot>src</SourcesRoot>
      <FileCopy Name="src/python/flaskapp/" Target="${libdir}flask-demo/flaskapp/"/>
      <SystemSetting Name="CSP.DefaultFileCharset" Value="UTF-8"/>

      <WSGIApplication
        Url="/my/flask/demo"
        UnauthenticatedEnabled="1"
        Description="Sample WSGI application using Flask"
        MatchRoles=":${dbrole}"
        WSGIAppLocation="${libdir}flask-demo/flaskapp/"
        WSGIAppName="app"
        WSGICallable="app"
       />
    <AfterInstallMessage>Module installed successfully!</AfterInstallMessage>     
    </Module>    
  </Document>
</Export>
0
0 39
Artigo Heloisa Paiva · Jun. 17, 2024 5m read

image

Olá Comunidade

Nesse artigo, vou introduzir minha aplicação irisChatGPT construída no LangChain Framework.

Primeiramente, vamos ter uma breve visão geral desse framework.
O mundo inteiro está falando sobre o ChatGPT e como as Large Language Models (LLMs - Grandes modelos de linguagem) se tornaram tão poderosas e tem performado além das expectativas, oferecendo conversas quase humanas. Isso é só o começo de como isso pode ser aplicado em qualquer empresa e qualquer domínio!

0
0 239
Artigo Heloisa Paiva · Jun. 12, 2024 4m read

Olá a todos! 

Trabalho há muitos anos com Excel e, ultimamente, foquei no tratamento de bases de dados.

Realmente minha experiencia com Excel foi para trabalhos financeiros, não tanto analíticos de dados em si, mas em um projeto recente pude trabalhar muito com SQL e me interessei um pouco pelo tema (não sou nenhuma uma especialista, já aviso!)

Me perguntei como poderia unir vários excels em um para, por exemplo, entregá-lo à Análise de dados utilizando a tecnologia InterSystems. Juntei toda a informação em um pequeno artigo. Espero que seja útil e, é claro, estou aberta a correções.

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

 

Problema

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

Motivação

0
0 87