新しい投稿

検索

質問
· 2024年11月4日

Objectscript to list source of a class

Hi,

I want to list the source if a class in an 'iris session'.

I know I can get a list of all classes in a namespace:

iris session <session> -U "%SYS"

DO $SYSTEM.OBJ.ShowClasses()

===

Is there a similar sinmple command to get the source of a class?

2 Comments
ディスカッション (2)2
続けるにはログインするか新規登録を行ってください
記事
· 2024年11月4日 3m read

第十一章 本地进程间通信(管道) - OPEN 命令管道示例

第十一章 本地进程间通信(管道) - OPEN 命令管道示例

OPEN 命令管道示例

以下是有效的命令管道OPEN语句。每个示例指定 10 秒的超时:

ディスカッション (0)1
続けるにはログインするか新規登録を行ってください
質問
· 2024年11月4日

Select query not returning all results

I'm running a query, joining nine tables together. When I run it with a SELECT COUNT(*) I get about 200,000 rows. When I run the SELECT with the columns I want, I get about 2,700 rows. Is there something inherent with the queries that limits the result set size, or anything I can do to make sure I'm getting back all the results? Rather, than trying to run it about 100 times limiting all previously gotten accounts.

2 Comments
ディスカッション (2)2
続けるにはログインするか新規登録を行ってください
記事
· 2024年11月4日 6m read

Modelos LLM e Aplicações RAG passo-a-passo - Parte II - Criando o contexto

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

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

O que é contexto?

Contexto refere-se a informações adicionais obtidas de uma fonte externa, como um banco de dados ou mecanismo de busca, para complementar ou melhorar as respostas geradas por um modelo de linguagem. O modelo de linguagem utiliza essas informações externas relevantes para gerar respostas mais precisas e detalhadas, em vez de confiar apenas no que aprendeu durante seu treinamento. O contexto ajuda a manter as respostas atualizadas e alinhadas com o tópico específico da consulta.

Este contexto pode ser informação armazenada em um banco de dados com ferramentas semelhantes às mostradas pelo nosso querido membro da comunidade  @José Pereira neste artigo ou informação não estruturada na forma de arquivos de texto com os quais alimentaremos o LLM, que será o caso que vamos tratar aqui.

Como gerar o contexto para nossa aplicação RAG?

A primeira e mais essencial coisa é, obviamente, ter toda a informação que consideramos relevante para as possíveis perguntas que vão ser feitas à nossa aplicação. Uma vez que esta informação está organizada de tal forma que seja acessível a partir da nossa aplicação, devemos ser capazes de identificar quais de todos os documentos disponíveis para o nosso contexto se referem à pergunta específica feita pelo utilizador. Para o nosso exemplo, temos uma série de documentos PDF (folhetos informativos de medicamentos) que queremos utilizar como possível contexto para as perguntas dos utilizadores da nossa aplicação.

Este ponto é fundamental para o sucesso de uma aplicação RAG, pois é tão ruim para a confiança do usuário responder com generalizações e vaguidão típicas de um LLM quanto responder com um contexto totalmente errado. É aqui que entram em cena nossos queridos bancos de dados vetoriais.

Bases de dados de vetores

Você provavelmente já ouviu falar de "bancos de dados vetoriais", como se fossem um novo tipo de banco de dados, como bancos de dados relacionais ou de documentos. Nada poderia estar mais longe da verdade. Esses bancos de dados vetoriais são bancos de dados padrão que suportam tipos de dados vetoriais, bem como operações relacionadas a eles. Vamos ver como esse tipo de dado será representado no projeto associado ao artigo:

Agora vamos ver como um registro seria exibido:

Bancos de dados de vetores... para quê?

Como explicamos no artigo anterior com LLMs, o uso de vetores é fundamental nos modelos de linguagem, pois eles podem representar conceitos e as relações entre eles em um espaço multidimensional. No caso em questão, essa representação multidimensional será a chave para identificar quais dos documentos em nosso contexto serão relevantes para a pergunta feita.

Perfeito, temos nosso banco de dados vetorial e os documentos que fornecerão o contexto, agora só precisamos registrar o conteúdo desses documentos em nosso banco de dados, mas... Com que critério?

Modelos para vetorização

Como? Outro modelo? O LLM não é suficiente para nós? Bem... não há necessidade de incomodar nosso LLM para vetorizar a informação do nosso contexto, podemos usar modelos de linguagem menores que sejam mais adequados às nossas necessidades para esta tarefa, como modelos treinados para detectar similaridades entre sentenças. Você pode encontrar uma infinidade deles no Hugging Face, cada um treinado com um conjunto específico de dados que nos permitirá melhorar a vetorização dos nossos dados.

E se isso não te convencer a usar um desses modelos para vetorização, basta dizer que geralmente esse tipo de modelo...

(São grátis)

Vamos ver em nosso exemplo como invocamos o modelo escolhido para essas vetorizações:

if not os.path.isdir('/app/data/model/'):
    model = sentence_transformers.SentenceTransformer('sentence-transformers/paraphrase-multilingual-MiniLM-L12-v2')            
    model.save('/app/data/model/')

Aqui estamos baixando o modelo escolhido para o nosso caso para o nosso computador local. Este mini-LM é multilíngue, por isso podemos vetorizar tanto em espanhol quanto em inglês sem nenhum problema.

Chunking

Se você já brincou com modelos de linguagem, provavelmente já enfrentou o desafio do chunking. O que é esse chunking? Muito simples, é a divisão do texto em fragmentos menores que podem conter um significado relevante. Por meio desse chunking do nosso contexto, podemos fazer consultas em nosso banco de dados vetorial que extraiam aqueles documentos do nosso contexto que possam ser relevantes em relação à pergunta feita.

Quais são os critérios para esse chunking? Bem, não há realmente um critério mágico que nos permita saber o quão longos nossos pedaços devem ser para serem o mais precisos possível. Em nosso exemplo, estamos usando uma biblioteca Python fornecida pelo langchain para realizar esse chunking, embora qualquer outro método ou biblioteca possa ser usado para isso:

text_splitter = RecursiveCharacterTextSplitter(
    chunk_size = 700,
    chunk_overlap  = 50,
)
path = "/app/data"
loader = PyPDFDirectoryLoader(path)
docs_before_split = loader.load()
docs_after_split = text_splitter.split_documents(docs_before_split)

Como você pode ver, o tamanho escolhido é de 700 caracteres, com uma sobreposição de 50 para evitar cortar palavras. Esses fragmentos extraídos de nossos documentos serão os que vetorizaremos e inseriremos em nosso banco de dados.

Esse processo de chunking pode ser otimizado tanto quanto você quiser por meio de "lematização", através da qual podemos transformar as palavras em seus respectivos lemmas (sem tempos, plurais, gênero, etc.) e assim eliminar certo ruído para a geração do vetor, mas não vamos entrar nisso, nesta página você pode ver uma explicação mais detalhada.

Vetorização de fragmentos

Ok, temos nossos fragmentos extraídos de cada um de nossos documentos, é hora de vetorizar e inserir em nosso banco de dados, vamos dar uma olhada no código para entender como podemos fazer isso.

for doc in docs_after_split:
    embeddings = model.encode(doc.page_content, normalize_embeddings=True)
    array = np.array(embeddings)
    formatted_array = np.vectorize('{:.12f}'.format)(array)
    parameters = []
    parameters.append(doc.metadata['source'])
    parameters.append(str(doc.page_content))
    parameters.append(str(','.join(formatted_array)))
    cursorIRIS.execute("INSERT INTO LLMRAG.DOCUMENTCHUNK (Document, Phrase, VectorizedPhrase) VALUES (?, ?, TO_VECTOR(?,DECIMAL))", parameters)
connectionIRIS.commit()

Como você pode ver, realizaremos os seguintes passos:

  1. Percorremos a lista de todos os fragmentos obtidos de todos os documentos que formarão nosso contexto.
  2. Para cada fragmento, vetorizamos o texto (usando a biblioteca sentence_transformers).
  3. Criamos um array usando a biblioteca numpy com o vetor formatado e o transformamos em uma string.
  4. Registramos as informações do documento com seu vetor associado em nosso banco de dados. Se você observar, estamos executando o comando TO_VECTOR que transformará a string do vetor que passamos para o formato apropriado.

Conclusão

Neste artigo vimos a necessidade de ter um banco de dados vetorial para a criação do contexto necessário em nossa aplicação RAG, também revisamos como cortar e vetorizar a informação do nosso contexto para seu registro nesse banco de dados.

No próximo artigo veremos como consultar nosso banco de dados vetorial com base na pergunta que o usuário envia ao modelo LLM e como, procurando por similaridades, construiremos o contexto que passaremos ao modelo. Não perca!

ディスカッション (0)1
続けるにはログインするか新規登録を行ってください
質問
· 2024年11月4日

Operation Email sender error #6034 connection with SMTP not successfull

I am developing a business operation that receives a request, creates a message with the data contained in it and sends it to an outlook email. For testing purposes both the sender and the destination are the same email account
This is the code:
Class BO.AlertEmailSender Extends Ens.BusinessOperation{

Parameter ADAPTER = "EnsLib.EMail.OutboundAdapter";
Property Adapter As EnsLib.EMail.OutboundAdapter;
Parameter INVOCATION = "Queue";
Method OnMessage(pRequest As Messages.AlertMsgToEmail, Output pResponse As Messages.AlertResponse) As %Status
{
    set sc = $$$OK
    Set msg = ##class(%Net.MailMessage).%New()
    Set msg.Subject=pRequest.mailObject
    set msg.From = pRequest.sender
    Do msg.To.Insert(pRequest.destination)
    Set msg.IsBinary=0
    Set msg.IsHTML=0
    set sc = msg.TextData.Write(pRequest.txtMessage)
    if $$$ISERR(sc) {    
        set ErrorText = "error: 'Write message stream error',"_$CHAR(10)_"details: '"_$SYSTEM.Status.DisplayError(sc)_"'"
        set ErrorCode = "WRT001"
        $$$LOGINFO(ErrorText)
    }
    Set smtp=##class(%Net.SMTP).%New()
    Set smtp.smtpserver="smtp-mail.outlook.com"
    Set smtp.port="587"
    //Set smtp.secure="STARTTLS"
    Set smtp.timezone="LOCAL"
    set smtp.SSLConfiguration = "smpt.office365.com"
    set smtp.UseSTARTTLS = 0
    Set auth=##class(%Net.Authenticator).%New()
    Set auth.UserName=pRequest.sender
    Set auth.Password="password"
    Set smtp.authenticator=auth
    Set smtp.AuthFrom=pRequest.sender
    //set auth.MechanismList = "PLAIN,LOGIN"
    Set sc=smtp.Send(msg)
    If $$$ISERR(sc) {
    Do $System.Status.DisplayError(sc)
    $$$LOGINFO(smtp.Error)
    Quit ""
  }
    // send email  
    //set sc = ..Adapter.SendMail(msg)
    // check for errors
    if sc {
        set report = "Email sent"
    } else {
        set report = "Email NOT sent"
        do $System.Status.DisplayError(sc)
        $$$LOGINFO("Send Failed: "_$System.Status.DisplayError(sc))
    }
    $$$LOGINFO("STATUS SEND: "_sc)
    set pResponse = ##class(Messages.AlertResponse).%New()
    set pResponse.msgStatus = report
    set pResponse.mailStatus = 1
    quit sc
}
}

In the InterSystems production portal I have set the operation, activated it and configured the base settings and connection settings as this
Server SMTP = smpt.office365.com
Port SMTP = 587
Credentials = credentials
Config SSL = smpt.office365

In the past I had obtained these errors: (translated from Italian)
-when I had wrongly defined smtpserver="smpt.office365.com" I obtained error #6031 "impossible to open connection TCP/IP"
- when SSLConfiguration was not present I obtained error #6034 "connection with server SMTP not successfull during command MAIL FROM:<READ>zSend+122^%Net.SMTP.1"
I do not receive anymore these errors after the corrections present in the code above, but I obtain error #6034
Connection with SMTP server not successfull during command init: <READ>zGetResponse+5^%Net.SMTP.1.
How do I proceed?

7 Comments
ディスカッション (7)4
続けるにはログインするか新規登録を行ってください