Nouvelle publication

Rechercher

Article
· Juin 6 2m de lecture

Converting Oracle Hierarchical Queries to InterSystems IRIS: Generating Date Ranges

If you're migrating from Oracle to InterSystems IRIS—like many of my customers—you may run into Oracle-specific SQL patterns that need translation.

Take this example:

SELECT (TO_DATE('2023-05-12','YYYY-MM-DD') - LEVEL + 1) AS gap_date
FROM dual
CONNECT BY LEVEL <= (TO_DATE('2023-05-12','YYYY-MM-DD') - TO_DATE('2023-05-02','YYYY-MM-DD') + 1);

In Oracle:

  • LEVEL is a pseudo-column used in hierarchical queries (CONNECT BY). It starts at 1 and increments by 1.
  • CONNECT BY LEVEL <= (...) determines how many rows to generate.
  • The difference between the two dates plus one gives 11, so the query produces 11 rows, counting backwards from May 12, 2023 to May 2, 2023.

Breakdown of the result:

LEVEL = 1  → 2023-05-12
LEVEL = 2  → 2023-05-11
...
LEVEL = 11 → 2023-05-02

Now the question is: How do you achieve this in InterSystems IRIS, which doesn’t support CONNECT BY?

One solution is to implement a SQL-style query using ObjectScript that mimics this behavior. Below is a sample CREATE QUERY definition that accepts a STARTDATE and a number of DAYS, and returns the descending list of dates.


✅ InterSystems IRIS: Implementing a Date Gap Query

CREATE QUERY GET_GAP_DATE(IN STARTDATE DATE, IN DAYS INT)
  RESULTS (GAP_DATE DATE)
  PROCEDURE
  LANGUAGE OBJECTSCRIPT

  Execute(INOUT QHandle BINARY(255), IN STARTDATE DATE, IN DAYS INT)
  {
    SET QHandle("start") = STARTDATE
    SET QHandle("days")  = DAYS
    SET QHandle("level") = 1
    RETURN $$$OK
  }

  Fetch(INOUT QHandle BINARY(255), INOUT Row %List, INOUT AtEnd INT)
  {
    IF (QHandle("level") > QHandle("days")) {
      SET Row = ""
      SET AtEnd = 1
    } ELSE {
      SET Row = $ListBuild(QHandle("start") - QHandle("level") + 1)
      SET QHandle("level") = QHandle("level") + 1
    }
    RETURN $$$OK
  }

  Close(INOUT QHandle BINARY(255))
  {
    KILL QHandle
    QUIT $$$OK
  }

You can run the above CREATE QUERY in IRIS System Management Portal, or through a tool like DBeaver or a Python/Jupyter notebook using JDBC/ODBC.


🧪 Example Usage:

To generate the same result as the Oracle query above, use:

SELECT * FROM GET_GAP_DATE(
  TO_DATE('2023-05-12', 'YYYY-MM-DD'),
  TO_DATE('2023-05-12', 'YYYY-MM-DD') - TO_DATE('2023-05-02', 'YYYY-MM-DD') + 1
);

This will output:

GAP_DATE
----------
2023-05-12
2023-05-11
...
2023-05-02
(11 rows)

🔁 Advanced Usage: Join with Other Tables

You can also use this query as a subquery or in joins:

SELECT * 
FROM GET_GAP_DATE(TO_DATE('2023-05-12', 'YYYY-MM-DD'), 11) 
CROSS JOIN dual;

This allows you to integrate date ranges into larger SQL workflows.


Hope this helps anyone tackling Oracle-to-IRIS migration scenarios! If you’ve built alternative solutions or have improvements, I’d love to hear your thoughts.

Discussion (0)1
Connectez-vous ou inscrivez-vous pour continuer
Article
· Juin 6 6m de lecture

Diseñar e implementar APIs REST en InterSystems IRIS a partir de especificaciones OpenAPI

​En el artículo anterior, Generación de Especificaciones OpenAPI, vimos qué es OpenAPI, por qué es útil para documentar los servicios REST y cómo generar un archivo de especificación en formato .yaml o .json. También exploramos cómo IRIS permite crear automáticamente esta documentación a partir del código existente, siguiendo el enfoque code-first.

Pero, ¿qué sucede si partimos del archivo OpenAPI en lugar del código? En otras palabras, ¿si primero definiéramos el comportamiento de nuestra API y luego generáramos las clases necesarias para implementarla en IRIS? Este método, conocido como enfoque specification-first, permite diseñar un servicio de manera clara y coherente, incluso antes de escribir la lógica de aplicación.

En este artículo veremos cómo utilizar este enfoque para construir una REST API completa en Intersystems IRIS a partir de una especificación OpenAPI 2.0.

Primer paso: construcción del archivo OpenAPI

El archivo OpenAPI 2.0 es un documento en formato JSON (o YAML) en el que se describen todas las API de la aplicación: las rutas disponibles (endpoints), los métodos HTTP soportados (GET, POST, PUT, DELETE...), los parámetros aceptados, las respuestas esperadas y mucho más.

Para construir correctamente este archivo, es fundamental conocer la estructura definida por el estándar OpenAPI 2.0
Algunos recursos útiles para profundizar son:

A continuación, se muestra un ejemplo sencillo de archivo openapi.json que define una API con un endpoint GET /hello:

{
  "swagger": "2.0",
  "info": {
    "title": "API example",
    "description": "Example of openAPI file",
    "version": "1.0.0"
  },
  "produces": [
    "application/json"
  ],
  "consumes": [
    "application/json"
  ],
  "paths": {
    "/hello": {
      "get": {
        "summary": "Sample greeting",
        "description": "Returns a greeting message",
        "responses": {
          "200": {
            "description": "OK",
            "schema": {
              "type": "string"
            }
          }
        },
        "operationId": "hello"
      }
    }
  }
}

Segundo paso: generación de las clases de la interfaz REST

Una vez creado el archivo de especificación, es posible utilizar una de las herramientas de gestión de APIs de InterSystems IRIS para generar automáticamente las tres clases principales que constituyen un servicio REST:

  • Clase de especificación (.spec)
    Subclase de %REST.Spec, que contiene la especificación OpenAPI 2.0 del servicio REST.
  • Clase de dispatch (.disp)
    Subclase de %CSP.REST, responsable de recibir las solicitudes HTTP y de invocar los métodos apropiados en la clase de implementación.
  • Clase de implementación (.impl)
    Subclase de %REST.Impl, contiene la implementación de la lógica de los métodos REST.

En este artículo se muestra cómo generar el servicio REST utilizando el servicio /api/mgmnt/.

Generación de las clases utilizando el servicio /api/mgmnt

  1. Utilizar Postman (o una herramienta similar) para crear un mensaje de solicitud HTTP como sigue:
    • Para la acción HTTP, seleccionar POST.
    • Para la URL, especificar una URL en el siguiente formato, usando la <baseURL> de tu instancia: https://<baseURL>/api/mgmnt/v2/namespace/myapp Donde namespace es el espacio de nombres en el que se desea crear el servicio REST y myapp es el nombre del paquete en el que se desea crear las clases. Ejemplo: http://localhost:1888/api/mgmnt/v2/myNamespace/Greetings  
    • En el cuerpo de la solicitud, pegar la especificación OpenAPI 2.0 de tu servicio web en formato JSON.
    • Especificar el tipo de contenido del cuerpo como JSON (application/json).
    • Como método de autenticación, usar Basic Auth e introducir como username y password las credenciales de un usuario con permisos de lectura/escritura sobre el espacio de nombres indicado.
  2. Enviar el mensaje de solicitud.
  • Caso de creación del servicio REST: si la llamada tiene éxito, InterSystems IRIS crea las clases .disp, .impl y .spec en el paquete del namespace especificado, y en Postman se recibirá el siguiente mensaje de confirmación:  { "msg": "New application myapp created" }
  • Caso de actualización del servicio REST: si la llamada tiene éxito, se recibirá el mensaje: {"msg": "Application lombardia.GUIConvenzioni.OMRREST updated"} Además, InterSystems IRIS regenerará completamente las clases .disp y .spec en el paquete especificado, y actualizará la clase .impl, conservando el código previamente implementado en ella. Atención: cualquier modificación manual realizada a la clase .disp será sobrescrita cada vez que se actualice la especificación, por lo que no se recomienda modificarla directamente.

Tercer paso: implementación de la lógica REST

Una vez generadas las tres clases (.spec, .disp, .impl), es momento de completar el servicio REST implementando la lógica de las operaciones.

Veamos un ejemplo concreto basado en la especificación mostrada anteriormente (que define un endpoint GET /hello).
Las clases generadas serán:

Clase Greetings.spec

Esta clase contiene la definición OpenAPI en formato JSON. No requiere modificaciones manuales, pero puede ser actualizada regenerándola mediante el servicio /api/mgmnt/ cada vez que se modifique la especificación.

Class Greetings.spec Extends Extends %REST.Spec [ ProcedureBlock ]
{

XData OpenAPI [ MimeType = application/json ]
  "swagger": "2.0",
  "info": {
    "title": "API example",
    "description": "Example of openAPI file",
    "version": "1.0.0"
  },
  ...
};
}

Clase Greetings.disp

Es la clase de dispatch la que conecta las rutas HTTP con los métodos de implementación. No es necesario (ni recomendable) modificarla, ya que se regenera cada vez que se actualiza la especificación.

Class Greetings.disp Extends %CSP.REST [ GeneratedBy = Greetings.spec.cls, ProcedureBlock ]
{

/// The class containing the RESTSpec which generated this class
Parameter SpecificationClass = "Greetings.spec";
/// Ignore any writes done directly by the REST method.
Parameter IgnoreWrites = 1;
/// Default the Content-Type for this application.
Parameter CONTENTTYPE = "application/json";
/// By default convert the input stream to Unicode
Parameter CONVERTINPUTSTREAM = 1;
/// The default response charset is utf-8
Parameter CHARSET = "utf-8";
XData UrlMap [ XMLNamespace = "http://www.intersystems.com/urlmap" ]
{
<Routes>
  <Route Url="/hello" Method="GET" Call="hello"/>
</Routes>

ClassMethod hello() As %Status
{
    Try {
        Do ##class(%REST.Impl).%SetContentType("application/json")
        If '##class(%REST.Impl).%CheckAccepts("application/json") Do ##class(%REST.Impl).%ReportRESTError(..#HTTP406NOTACCEPTABLE,$$$ERROR($$$RESTBadAccepts)) Quit
        Set response=##class(Greetings.impl).hello()
        Do ##class(Greetings.impl).%WriteResponse(response)
    } Catch (ex) {
        Do ##class(%REST.Impl).%ReportRESTError(..#HTTP500INTERNALSERVERERROR,ex.AsStatus(),$parameter("Greetings.impl","ExposeServerExceptions"))
    }
    Quit $$$OK
}
}

Como se puede observar, esta clase mapea el endpoint /hello al método hello() presente en la clase Greetings.impl.

Clase Greetings.impl

Esta es la clase en la que se escribe la lógica de aplicación propiamente dicha. Es una subclase de %REST.Impl y se genera con métodos “vacíos” que deben ser implementados.

Class Greetings.impl Extends %REST.Impl [ ProcedureBlock ]
{
/// Returns a greeting message
ClassMethod hello() As %Status
{
  //write here your code..
}
}

Conclusión

Hemos visto cómo, a partir de una especificación OpenAPI 2.0, es posible construir una interfaz REST completa en InterSystems IRIS siguiendo el enfoque specification-first. Con unos pocos pasos, el framework nos proporciona una estructura lista para usar sobre la cual integrar nuestra lógica de negocio, permitiéndonos desarrollar APIs de manera clara, ordenada y escalable.

En el próximo artículo veremos cómo exponer efectivamente el servicio REST a través de una aplicación web de IRIS.

Discussion (0)2
Connectez-vous ou inscrivez-vous pour continuer
Article
· Juin 6 3m de lecture

Un coup de poids

image

Tel un coup de grâce, sans laisser aucune chance à l'adversaire, Kubernetes, plateforme open source, offre un univers de possibilités grâce à sa disponibilité (c'est-à-dire la facilité d'accès au support, aux services et aux outils). Cette plateforme permet de gérer les tâches et les services dans des conteneurs, ce qui simplifie grandement la configuration et l'automatisation de ces processus.

Discussion (0)1
Connectez-vous ou inscrivez-vous pour continuer
Article
· Juin 6 4m de lecture

Customize Your Marathi Wedding Card Online

Customize Your Marathi Wedding Card Online – Lagnpatrika Templates

Weddings are an expression of love, tradition, and joy—especially in Maharashtrian culture, where every ritual holds emotional significance. One of the first and most essential steps in announcing your special day is through a beautifully crafted Marathi wedding card, or Lagnpatrika. At Crafty Art, we help you design this first impression with elegance and cultural authenticity, offering an intuitive way to customize your Marathi wedding card online using professionally designed Lagnpatrika templates.

A Blend of Tradition and Modern Design

Our online collection of Marathi wedding invitation card templates is deeply rooted in traditional values while also embracing modern aesthetics. Whether you're planning a grand Maharashtrian wedding or a simple, intimate ceremony, Crafty Art provides a wide range of styles—from traditional motifs like mangal kalash, peacocks, and turmeric leaves to minimalistic and elegant floral themes.

Each template is carefully designed by artists who understand the essence of Maharashtrian culture. You can choose fonts that resemble traditional script styles and select layouts that reflect religious and ceremonial importance. These elements ensure that your invite not only looks beautiful but also feels heartfelt and personal.

Easy Customization in Marathi and English

One of the biggest challenges faced when creating a digital Lagnpatrika is language integration. With Crafty Art, you can customize your wedding invitation in both Marathi and English with ease. Whether you want your invite to be entirely in Marathi for a traditional touch or bilingual for wider accessibility, we make it simple.

Our user-friendly platform allows you to edit names, wedding dates, venues, RSVP details, and more. You can even personalize the invitation with spiritual quotes, family names, and cultural blessings—all in your chosen language. There’s no need for any graphic design skills; just choose a template, edit the content, and your perfect invite is ready in minutes.

Unique Features for a Personal Touch

Crafty Art offers unique features to ensure your wedding card stands out:

  • Photo Upload: Add your pre-wedding photos, couple portraits, or even family pictures to the invite.
  • Color Palette Options: Match your card’s color scheme with your wedding theme—traditional saffron, rich maroon, elegant gold, or soothing pastels.
  • Music Integration: For digital invitations, you can embed soft instrumental music or a Marathi wedding song to give your invite an emotional tone.
  • Digital and Print Ready: Once customized, your Lagnpatrika can be downloaded in high-quality formats, ready for digital sharing via WhatsApp or email and suitable for professional printing.

Eco-Friendly and Cost-Effective

Creating your Marathi wedding card online is not only quick and easy—it’s also environmentally conscious. With digital invitations, you reduce the need for paper, printing, and physical delivery, helping to create a more sustainable celebration. It also significantly lowers your invitation costs while still allowing you to maintain elegance and quality.

Suitable for Every Wedding Function

Whether it's the main wedding ceremony, engagement (saka har), haldi, mehendi, sangeet, or muhurt, you can find and customize invitation templates for every occasion on Crafty Art. Our platform gives you the flexibility to maintain a consistent design theme across all your invites, adding harmony and aesthetic appeal to your entire wedding journey.

How It Works

  1. Browse Templates: Explore a wide selection of Lagnpatrika templates categorized by style and occasion.
  2. Customize Content: Use the easy editor to enter your wedding details, select fonts, and change colors or images.
  3. Preview Instantly: View your customized invitation in real time.
  4. Download or Share: Download the card for printing or send it digitally to your guests.

Why Choose Crafty Art?

Crafty Art Customize Marathi Wedding Invitation combines the richness of Marathi culture with the ease of modern technology. Our platform ensures you don’t need a professional designer or printer to get a beautiful wedding card. Every couple deserves a wedding invitation that reflects their story, values, and heritage—and that’s what we deliver.

From traditional aesthetics to modern simplicity, from paper-ready formats to social media sharing, Crafty Art supports every couple in creating an invitation that’s not just seen—but remembered.

Marathi Wedding Card Online | Lagnpatrika Templates | Customize Marathi Wedding Invitation

Discussion (0)1
Connectez-vous ou inscrivez-vous pour continuer
Article
· Juin 5 18m de lecture

Uso de Python en InterSystems Iris

Uso de Python en InterSystems Iris

Hola

En este artículo veremos el uso de python como lenguaje de programación en InterSystems Iris. Para ello, utilizaremos como referencia la versión de Community 2025.1 que está disponible para ser descargada en https:// download.intersystems.com iniciando sesión en el entorno. Para obtener más información sobre cómo descargar e instalar Iris, consulte el enlace de la comunidad https://community.intersystems.com/post/how-download-and-install-intersystems-iris

Una vez instalado el iris, ahora necesitamos tener python disponible en nuestro entorno. Tenemos varios tutoriales que explican la instalación y configuración de python en Iris. Una buena fuente de referencia es el enlace a la documentación oficial de InterSystems en https://docs.intersystems.com/irislatest/csp/docbook/DocBook.UI.Page.cls?KEY=AFL_epython

Una vez que hemos instalado y configurado python en Iris, podemos hacer una primera prueba: abrir el shell de python a través del terminal Iris. Para ello, abriremos una ventana de terminal Iris y ejecutaremos el comando Do $SYSTEM. Python.Shell():

Fig. 1 – Pantalla de concha de Python en Iris

Si tienes tu entorno configurado correctamente, verás la pantalla de arriba. A partir de ahí podemos ejecutar comandos, como ver la versión de python. Para ello utilizaremos el módulo sys:

Fig. 2 – Pantalla de concha de Python en Iris

Listo. Tenemos a Iris y python listas para trabajar. Ahora podemos crear, por ejemplo, una clase Iris y programar algunos métodos usando python en ella. Veamos un ejemplo:

Class Demo.Pessoa Extends %Persistent
{

Property nome As %String;

Method MeuNome() [ Language = objectscript ]
{
              write ..nome
}

Method MeuNomePython() [ Language = python ]
{
              print(self.nome)
}
}

 La clase anterior tiene una propiedad (nombre) y dos métodos, uno en objectscript y otro en python, solo para comparar. Llamando a estos métodos, tenemos el resultado en la siguiente pantalla:

 

Fig. 3 – Llamada al método en Iris

 

 

Vea entonces que podemos tener en la misma clase métodos codificados en objectscript y en python. Y de uno de ellos podemos llamar al otro. Vea el siguiente ejemplo. Vamos a crear un nuevo método GetKey y desde el método MyPythonName vamos a hacer una llamada y recuperar la información:

Method MeuNomePython() [ Language = python ]
{
              chave=self.GetChave()
              print(self.nome)
              print(chave)
}

Method GetChave() As %Integer [ Language = objectscript ]
{
              Return $Get(^Chave)
}

Vamos a crear uno global con el valor que queremos que se recupere:

Fig. 4 – Creación de global en Iris

Listo. Con el global created, llamemos ahora a nuestro método:

Fig. 5 – Llamada al método en Iris

 

Observe que ahora nuestro método python hace una llamada a otro método, este codificado en objectscript. Lo contrario también es cierto.

Python tiene una serie de bibliotecas útiles, como:

  • iris: permite la interacción con la base de datos y el entorno de Iris
  • matplot – Visualización de datos y gráficos
  • numpy: proporciona soporte para matrices y estructuras de datos
  • scikit-learn: le permite crear e implementar modelos de aprendizaje automático
  • pandas: se utiliza para la manipulación y el análisis de datos

Otra característica presente en Iris con python es la posibilidad de acceder a los datos vía SQL, es decir, podemos tener los datos almacenados en tablas en Iris y código python consumiendo estos datos. Veamos un ejemplo de código que lee una tabla Iris y genera un archivo XLS utilizando la biblioteca Iris y Pandas:

ClassMethod tabela() As %Status [ Language = python ]
{

              import iris
              import pandas as pd
             
              rs = iris.sql.exec("select * from demo.alunos")
              df = rs.dataframe()   
              caminho_arquivo = 'c:\\temp\\dados.xlsx'
              df.to_excel(caminho_arquivo, index=False)
             
              return True
}

Como se ve, usamos las bibliotecas iris y pandas en el código. A continuación, creamos un conjunto de registros (rs) con el comando SQL deseado y después de eso un marco de datos pandas (df) de este conjunto de registros. Desde el marco de datos, exportamos los datos de la tabla a un archivo de Excel en la ruta especificada (df.to_excel). Fíjate que con muy pocas líneas armamos un código extremadamente útil. Aquí el uso de las bibliotecas de python fue clave. Ya nos han proporcionado el soporte para el dataframe (pandas) y a partir de ahí su manipulación (to_excel). Ejecutando nuestro código, tenemos la tabla de Excel generada a partir de los datos de la tabla:

Fig. 6 – Llamada al método en Iris

 

Fig. 7 – Hoja de trabajo generada por el método

 

Python tiene varias bibliotecas listas para usar con varias características, así como una gran cantidad de código en comunidades que se puede usar en aplicaciones.

Uno de ellos, que mencionamos anteriormente, es scikit-learn, que permite el uso de varios mecanismos de regresión, permitiendo la creación de métodos de predicción basados en información, como una regresión lineal. Podemos ver un ejemplo de código de regresión a continuación:

ClassMethod CalcularRegressaoLinear() As %String [ Language = python ]
{
    import iris
    import json

    import pandas as pd
    from sklearn.linear_model import LinearRegression
    from sklearn.metrics import mean_absolute_error
    import numpy as np
    import matplotlib
    import matplotlib.pyplot as plt
    matplotlib.use("Agg")
    
    rs = iris.sql.exec("select venda as x, temperatura as y from estat.fabrica")
    df = rs.dataframe()
    
    print(df)
    
    # Reformatando x1 para uma matriz 2D exigida pelo scikit-learn
    X = df[['x']]
    y = df['y']     # Inicializa e ajusta o modelo de regressão linear
    model = LinearRegression()
    model.fit(X, y)     # Extrai os coeficientes da regressão
    coeficiente_angular = model.coef_[0]
    intercepto = model.intercept_
    r_quadrado = model.score(X, y)
    
    # Calcula Y_pred baseado no X
    Y_pred = model.predict(X)
            
    # Calcula MAE
    MAE = mean_absolute_error(y, Y_pred)     # Previsão para a linha de regressão
    x_pred = np.linspace(df['x'].min(), df['x'].max(), 100).reshape(-1, 1)
    y_pred = model.predict(x_pred)     # Geração do gráfico de regressão
    plt.figure(figsize=(8, 6))
    plt.scatter(df['x'], df['y'], color='blue', label='Dados Originais')
    plt.plot(df['x'], df['y'], color='black', label='Linha dos Dados Originais')
    plt.scatter(df['x'], Y_pred, color='green', label='Dados Previstos')
    plt.plot(x_pred, y_pred, color='red', label='Linha da Regressão')
    plt.scatter(0, intercepto, color="purple", zorder=5, label="Ponto do intercepto")
    plt.title('Regressão Linear')
    plt.xlabel('X')
    plt.ylabel('Y')
    plt.legend()
    plt.grid(True)     # Salvando o gráfico como imagem
    caminho_arquivo = 'c:\\temp\\RegressaoLinear.png'
    plt.savefig(caminho_arquivo, dpi=300, bbox_inches='tight')
    plt.close()
        
    # Formata os resultados em JSON
    resultado = {
        'coeficiente_angular': coeficiente_angular,
        'intercepto': intercepto,
        'r_quadrado': r_quadrado,
        'MAE': MAE
    }     return json.dumps(resultado)
}

El código lee una tabla en Iris a través de SQL, crea un dataframe pandas basado en los datos de la tabla y calcula una regresión lineal, generando un gráfico con la línea de regresión, además de traer indicadores de regresión. Todo esto desde la biblioteca scikit-learn.

El artículo https://pt.community.intersystems.com/post/usando-o-python-no-intersystems-iris-%E2%80%93-calculando-uma-regress%C3%A3o-linear-simples  proporciona más información sobre el uso de scikit-learn para calcular la regresión lineal.

Iris también permite el almacenamiento de datos vectoriales, lo que abre numerosas posibilidades. La biblioteca langchain_iris trae mecanismos que ayudan en el almacenamiento y recuperación de información en bases de datos vectoriales.

El siguiente código toma un archivo PDF y genera una base de datos vectorial con las incrustaciones generadas para futuras recuperaciones de datos:

ClassMethod Ingest(collectionName As %String, filePath As %String) As %String [ Language = python ]
{     import json
    from langchain_iris import IRISVector
    from langchain_openai import OpenAIEmbeddings
    from langchain_community.document_loaders import PyPDFLoader     try:
        apiKey = <chatgpt_api_key>
        loader = PyPDFLoader(filePath)
        splits = loader.load_and_split()
        vectorstore = IRISVector.from_documents(
            documents=splits,
            embedding=OpenAIEmbeddings(openai_api_key=apiKey),
            dimension=1536,
            collection_name=collectionName,
        )
        return json.dumps({"status": True})
    except Exception as err:
        return json.dumps({"error": str(err)})
}

 

Al leer el archivo PDF, se "divide" en partes y estas piezas se almacenan en forma de incrustaciones en Iris. Las incrustaciones son vectores que representan esa división.

Fig. 8 – Tabla con columna vectorial en Iris

 

Una vez que se ha ingerido el archivo, ahora podemos recuperar información y pasarla al LLM para generar un texto de retorno basado en una pregunta formulada. La pregunta se convierte en vectores y se busca en la base de datos. A continuación, los datos recuperados se envían a LLM, que da formato a una respuesta. En el ejemplo usamos ChatGPT:

Fig.9 – Llamada al método en Iris

 

A continuación se muestra el código de la búsqueda realizada:

ClassMethod Retrieve(collectionName As %String, question As %String, sessionId As %String = "") [ Language = python ]
{
    import json
    import iris
    from langchain_iris import IRISVector
    from langchain_community.chat_message_histories import ChatMessageHistory
    from langchain_core.chat_history import BaseChatMessageHistory
    from langchain_core.runnables.history import RunnableWithMessageHistory
    from langchain_openai import ChatOpenAI, OpenAIEmbeddings    

    from langchain.chains import create_history_aware_retriever
    from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder
    from langchain.chains import create_retrieval_chain
    from langchain.chains.combine_documents import create_stuff_documents_chain

    
    try:
        
        apiKey = <chatgpt_api_key>
        model = "gpt-3.5-turbo"
        llm = ChatOpenAI(model= model, temperature=0, api_key=apiKey)
        embeddings = OpenAIEmbeddings(openai_api_key=apiKey)         vectorstore = IRISVector(
            embedding_function=OpenAIEmbeddings(openai_api_key=apiKey),
            dimension=1536,
            collection_name=collectionName,
        )         retriever = vectorstore.as_retriever()         contextualize_q_system_prompt = """Dado um histórico de bate-papo e a última pergunta do usuário \
        que pode fazer referência ao contexto no histórico do bate-papo, formule uma pergunta independente \
        que pode ser entendido sem o histórico de bate-papo. NÃO responda à pergunta, \
        apenas reformule-o se necessário e devolva-o como está."""
        
        contextualize_q_prompt = ChatPromptTemplate.from_messages(
            [
                ("system", contextualize_q_system_prompt),
                MessagesPlaceholder("chat_history"),
                ("human", "{input}"),
            ]
        )
        history_aware_retriever = create_history_aware_retriever(
            llm, retriever, contextualize_q_prompt
        )         qa_system_prompt = """
                            Você é um assistente inteligente que responde perguntas com base em dados recuperados de uma base. Dependendo da natureza dos dados, você deve escolher o melhor formato de resposta:                             1. **Texto:** Se os dados contêm principalmente informações descritivas ou narrativas, responda em formato de texto.
                           
                            2. **Tabela:** Se os dados contêm informações estruturadas (ex: listas, valores, métricas, comparações diretas), responda em formato HTML com o seguinte estilo:
                               - Bordas de 1px sólidas e de cor #dddddd.
                               - O cabeçalho deve ter um fundo cinza escuro (#2C3E50) e texto em branco.
                               - As células devem ter padding de 8px.
                               - As linhas pares devem ter um fundo cinza claro (#f9f9f9).
                               - As linhas devem mudar de cor ao passar o mouse sobre elas, usando a cor #f1f1f1.
                               - O texto nas células deve estar centralizado.                             3. **Lista:** Se os dados contêm informações estruturadas (ex: listas, valores, métricas, comparações diretas), responda em formato HTML com o seguinte estilo:
                               - Bordas de 1px sólidas e de cor #dddddd.
                               - O cabeçalho deve ter um fundo cinza escuro (#2C3E50) e texto em branco.
                               - As células devem ter padding de 8px.
                               - As linhas pares devem ter um fundo cinza claro (#f9f9f9).
                               - As linhas devem mudar de cor ao passar o mouse sobre elas, usando a cor #f1f1f1.
                               - O texto nas células deve estar centralizado.
                                                        
                            4. **Gráfico:** Se os dados contêm informações que são mais bem visualizadas em um gráfico (ex: tendências, distribuições, comparações entre categorias), gere um gráfico apropriado. Inclua um título, rótulos de eixo e uma legenda quando necessário. Responda utilizando um link do quickchart.io.
                                                        
                            Contexto: {context}
                            Pergunta: {input}
                            """
        
        qa_prompt = ChatPromptTemplate.from_messages(
            [
                ("system", qa_system_prompt),
                MessagesPlaceholder("chat_history"),
                ("human", "{input}"),
            ]
        )         question_answer_chain = create_stuff_documents_chain(llm, qa_prompt)
        rag_chain = create_retrieval_chain(history_aware_retriever, question_answer_chain)         def get_session_history(sessionId: str) -> BaseChatMessageHistory:
            rs = iris.sql.exec("SELECT * FROM (SELECT TOP 5 pergunta, resposta, ID FROM Vector.ChatHistory WHERE sessionId = ? ORDER BY ID DESC) SUB ORDER BY ID ASC", sessionId)
            history = ChatMessageHistory()
            for row in rs:
                history.add_user_message(row[0])
                history.add_ai_message(row[1])
            return history         def save_session_history(sessionId: str, pergunta: str, resposta: str):
            iris.sql.exec("INSERT INTO Vector.ChatHistory (sessionId, pergunta, resposta) VALUES (?, ?, ?) ", sessionId, pergunta, resposta)         conversational_rag_chain = RunnableWithMessageHistory(
            rag_chain,
            get_session_history,
            input_messages_key="input",
            history_messages_key="chat_history",
            output_messages_key="answer",
        )         ai_msg_1 = conversational_rag_chain.invoke(
            {"input": question, "chat_history": get_session_history(sessionId).messages},
            config={
                "configurable": {"session_id": sessionId}
            },
        )
        
        save_session_history(sessionId, question, str(ai_msg_1['answer']))
        return str(ai_msg_1['answer'])
    except Exception as err:
        return str(err)
}

 

Aquí en este código entran varios aspectos que deben tenerse en cuenta en este tipo de código, como el contexto de la conversación, el prompt de LLM, las incrustaciones y la búsqueda vectorial.

E incluso podemos tener una interfaz para realizar las llamadas al método, lo que le da un aspecto más sofisticado a la consulta. En el ejemplo tenemos una página web accediendo a una api REST que llama al método de consulta:

 

Fig. 10 – Llamada a la API REST en la pantalla de la aplicación web en Iris

 

Estos son ejemplos del uso de python en Iris. Pero el universo de bibliotecas disponibles es mucho mayor. Podemos usar bibliotecas para reconocimiento de imágenes, OCR, biometría, estadísticas y más.

Discussion (0)1
Connectez-vous ou inscrivez-vous pour continuer