发布新帖

查找

文章
· 三月 28, 2024 阅读大约需 1 分钟

How to register and reference task schedules programmatically

InterSystems FAQ rubric

Here, we will introduce a sample code for registering and referencing task schedules.

 ①Sample of task schedule registration

*Create a task to execute do ^TEST every day at 1:00 am. 

 set task=##class(%SYS.Task).%New()
 set task.Name="MyTask1"
 set taskDescription="Execute ^xxx every day at 1:00 AM" // Optional
 set task.NameSpace="USER"
 set task.TimePeriod=0
 set task.DailyFrequency=0
 set task.DailyFrequencyTime=""
 set task.DailyIncrement=""
 set task.DailyStartTime=$ZTimeh("01:00:00")
 set task.DailyEndTime=""
 set task.TaskClass="%SYS.Task.RunLegacyTask"
 set task.Settings=$LB("ExecuteCode","do ^TEST") // Set ExecuteCode for RunLegacyTask
 write task.%Save()

② Sample of task schedule reference

*The contents registered in the task schedule are obtained programmatically.

USER>set task=##class(%SYS.Task).%OpenId(1) USER>zwrite tasktask=<object reference="">[14@%SYS.Task]

+----------------- attribute values ------------------
| %Concurrency = 1
| DailyEndTime = 0
| DailyFrequency = 0
| DailyFrequencyTime = ""
| DailyIncrement = ""
| DailyStartTime = 0
| DayNextScheduled = 63877
| DeleteAfterRun = 0
| Description = "Journal files are switched at midnight every day."

// If you want to refer to individual items, do the following:
USER>write $ZDT(task.DayNextScheduled)
11/21/2015
USER>write task.Name
Journal switching
USER>

2 Comments
讨论 (2)2
登录或注册以继续
问题
· 三月 28, 2024

How to split the two timestamp based on interval time in IRIS Database?

I have two timestamp values and also I have interval time, I need to split the timestamp based on the interval time. Like 

Start Time is '2024-01-01T10:00:00'
End Time is '2024-01-01T11:00:00'
Interval Time is 15 minutes

I expected the result is:

'2024-01-01T10:15:00'
'2024-01-01T10:30:00'
'2024-01-01T10:45:00'
'2024-01-01T11:00:00'

11 Comments
讨论 (11)1
登录或注册以继续
文章
· 三月 28, 2024 阅读大约需 3 分钟

InterSystems通过向量搜索扩展了InterSystems IRIS数据平台,支持下一代人工智能应用

2024年3月26日,InterSystems数据平台全球主管Scott Gnau发文,宣布InterSystems IRIS数据平台新增了向量搜索(vector search)功能。

本文作者为Scott Gnau,InterSystems数据平台全球主管。

人工智能具备变革性潜力,能够从数据中获取价值和洞察力。我们正在迈向一个几乎所有应用都将通过人工智能来驱动的世界,随之而来的,是构建这些应用的开发人员需要正确的工具从这些应用中创造体验。因此,InterSystems非常高兴地宣布这一消息——IRIS数据平台新增了向量搜索(vector search)功能。

在使用大型语言模型时,像向量搜索这样的工具对于从海量数据集中高效、准确地检索相关信息至关重要。通过将文本和图像转换为高维向量,这些技术可以支持快速比较和搜索,即便处理分散在整个组织、不同数据集的数百万个文件时也是如此。

InterSystems IRIS数据平台为下一代应用提供了统一基础

在InterSystems,我们始终在探寻各种方式,使下一代数据处理尽可能地离客户数据近一些,而无需将数据传输到特定系统。将向量搜索功能添加至InterSystems IRIS数据平台后,我们可以通过向量嵌入(vector embedding)对数据平台进行搜索,从而增强软件在自然语言处理(NLP)、文本和图像分析相关任务中的功能。这种集成将使开发人员能够更轻松地创建使用生成式人工智能的应用程序,以完成各种用例的复杂任务,并根据InterSystems处理的专有数据(proprietary data)提供即时响应。这也意味着他们可以使用精巧的向量化索引来完成这项工作,同时对保持内部专有产权情报的安全充满信心。

这一功能支持InterSystems IRIS数据平台管理和查询内容及相关的密集向量嵌入,特别是能够与RAG集成,开发基于生成式人工智能的应用。随着可用工具集的快速发展,无缝RAG集成可支持新模型和用例的敏捷采用。

这项技术能够给客户带来哪些益处?

BioStrand是一家依赖于人工智能的药物发现公司,也是InterSystems创新计划(InterSystems Innovation Program)的一部分(该计划帮助初创企业在我们的IRIS平台上构建应用)。BioStrand的核心产品是Lensai平台,这是一种多功能解决方案,支持包括抗体药物发现和设计在内的各种应用。通过先进的算法,Lensai可以迅速识别并设计新型药物化合物,大大缩短了从开发到商业化的研发时间。该模型将采用先进堆叠技术的大型语言模型(LLM)的优势与BioStrand的专利技术HYFT独特地结合在一起。

HYFT是一种嵌入类型,在生物序列中充当独一无二的“指纹”,使BioStrand能够高精度地分配来自不同LLM的嵌入。这个基础模型代表着一个庞大且不断扩展的知识图谱,在6.6亿个数据对象中映射了250亿种关系,令人印象深刻。这个全面的图谱将整个生物圈的序列、结构、功能以及书目信息相互连接在一起。它还融合了检索增强生成、SQL向量搜索等尖端技术,以及LLM的生成能力和知识图谱的语义表达能力。

向量搜索将从根本上改变开发人员与IRIS的交互方式

在实施这项技术方面,我们还只是刚刚起步。随着客户与数据的交互方式因向量搜索而得到改变,随着新的人工智能应用不断通过应用向量搜索而得到开发,我们将分享更多客户故事。与此同时,我也推荐您访问我们的向量搜索页面,了解更多信息。

我们加速创新,确保客户成功,并展示对卓越的承诺,与此同时,我们致力于维护最高标准的隐私、安全和责任,这将引导我们以一种深思熟虑、公正的方式对待人工智能,从而创造信任。我们相信,透明度、责任感和可解释性是建立对人工智能系统的信任并推动其创新的关键。

讨论 (0)1
登录或注册以继续
文章
· 三月 27, 2024 阅读大约需 2 分钟

A Better data import experience for LOAD DATA

In recent versions of IRIS, a powerful new data loading command has been introduced to SQL: LOAD DATA. This feature has been highly optimized to import data into IRIS extremely fast, allowing hundreds of gigabytes of data to be inserted in seconds instead of hours or days. 

This is a very exciting improvement. However, a big problem in the data loading experience still exists. Namely, the time and hassle it takes to:

  1. Define the schema for the table in which you want to load data.
  2. Figure out the syntax for the LOAD DATA command.

I've developed a user interface that invisibly handles the CREATE TABLE step and then generates the syntax for LOAD DATA, all in a handy wizard!

At least in my case -- although I've been in the database business for decades -- I only import data a few times a year. Therefore, my CREATE TABLE skills get rusty, and it's really nice to have a tool take care of that for me. And this tool doesn't just handle syntax. It also inspects the input CSV file using a utility from the SQL Utilities library from @Benjamin De Boe to figure out the data types and their length. Then it asks a few more questions to define the syntax of the required LOAD DATA command. The app can run it, or you can just copy the syntax and tweak it yourself. 

Here's a walkthrough.

Step 1: Install the app and review the CSV file

After following the instructions to install the solution, you will have an Angular app published as a CSP application and a backend ObjectScript application that serves as the API to interface with the database.

Take a look at my sample data set (using the Rainbow CSV extension in VS Code). It has a mix of numeric, text and empty columns.

Step 2: Go to the app

You will probably find the app at http://localhost:52773/csp/dataloadapp/index.html if you use the default IRIS port and web application name.

Step 3: Specify the CSV file location

Step 4: Specify the CSV file's format

LOAD DATA needs to know some things like the column delimiter character and where to start in the file. 

Step 5: Define a destination table name, with the schema name as well

Step 6: Fine tune the field names and data types

Most of this will be filled in for you, and should be pretty accurate, but you will probably want to adjust some names or field lengths.

And that's it! Press "Load CSV" and the client-side app will make a call to the server to run a CREATE TABLE SQL command, then run LOAD DATA with the syntax shown in the black box on the right. Going into the Management Portal (or any other SQL client), you can see I now have the CSV file loaded into IRIS.

 

I must apologize in advance that there isn't much error checking yet, but this is open source so if you find this tool useful, join me in improving it on GitHub.

6 Comments
讨论 (6)3
登录或注册以继续
文章
· 三月 27, 2024 阅读大约需 6 分钟

Boosting facial recognition with Vector Search

As you have seen in the latest community publications, InterSystems IRIS has included since version 2024.1 the possibility of including vector data types in its database and based on this type of data vector searches have been implemented. Well, these new features reminded me of the article I published a while ago that was based on facial recognition using Embedded Python.

Introduction

For those of you who don't remember what that article was about, it is linked at the end of this article. The way the application worked was to recognize the faces present in any image and subsequently compare it with the faces that we had already identified in our IRIS instance, indicating who it belonged to.

How could we improve our facial recognition application by taking advantage of these new features? Well, the main problem we found in our project is performance. Having to recalculate the vector for each image in our system and compare it to the image to be identified is a time-consuming process that can be greatly improved with vector search.

Let's see how we could implement it with the Open Exchange project that we have associated.

Example project

The project is going to deploy a container in Docker with the latest released version of InterSystems IRIS (as of the date of publication of this article, 2024.1) in which we will create the table on which we will store the images with which to compare. To do this we will launch the following command from the database:

CREATE TABLE Vectorface_Data.Person (name VARCHAR(50), description VARCHAR(1000), photo VECTOR(DECIMAL, 128))

As you can see, our photo column will be a vector with 128 decimal values. Next we are going to deploy a web application in our instance that we will call from Postman:

This web application will use the Vectorface.WS.Service class, which will be responsible for processing the information received by HTTP POST from Postman.

Let's take a look at said class, first the route map:

XData UrlMap [ XMLNamespace = "https://www.intersystems.com/urlmap" ]
{
<Routes>
	<Route Url="/checkSimilarity" Method="POST" Call="CheckSimilarity" />
	<Route Url="/savePhoto" Method="POST" Call="SavePhoto" />
</Routes>
}

We are going to work with two URLs:

  • /savePhoto: responsible for receiving the photo in base64, analyzing it, vectorizing the image and storing it in the database.
  • /checkSimilarity: which will vectorize the image for comparison and launch the query to the database looking for the most similar image.

Saving photos in IRIS:

ClassMethod SavePhoto() 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
        // Reading the body of the http call with the person data
        set dynamicBody = {}.%FromJSON(%request.Content)

        set dynamicStream = dynamicBody.%Get("fileData",,"stream<base64")

        set stream=##class(%Stream.FileBinary).%New()
        set sc=stream.LinkToFile("/shared/durable/"_dynamicBody.fileName)
        set sc=stream.CopyFromAndSave(dynamicStream)

        set imageVector = ..Checker("/shared/durable/"_dynamicBody.fileName)       
        set imageVector = $REPLACE(imageVector, $CHAR(13,10),",")
        set imageVector = $REPLACE(imageVector,"['","")
        set imageVector = $REPLACE(imageVector,"']","")
        set imageVector = $REPLACE(imageVector,"'","")
        set imageVector = $REPLACE(imageVector," ",",")

        &sql(INSERT INTO Vectorface_Data.Person VALUES (:dynamicBody.name, :dynamicBody.description, TO_VECTOR(:imageVector, DECIMAL)))

        Do ##class(%REST.Impl).%SetStatusCode("200")
        Do ##class(%REST.Impl).%WriteResponse(imageVector)
        return {"result": "Picture stored"}
        
    } Catch (ex) {
        Do ##class(%REST.Impl).%SetStatusCode("400")
        Do ##class(%REST.Impl).%WriteResponse(ex.DisplayString())
        return {"errormessage": "Client error"}
    }
    Quit $$$OK
}

This function transforms the base64 into a file that is subsequently sent to the Python Checker function, responsible for identifying the face and vectorizing it. With the recovered vector we will insert it into our database in vector format.

Comparing vector images with the database

ClassMethod CheckSimilarity() 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
        // Reading the body of the http call with the person data
        set dynamicBody = {}.%FromJSON(%request.Content)

        set dynamicStream = dynamicBody.%Get("fileData",,"stream<base64")

        set stream=##class(%Stream.FileBinary).%New()
        set sc=stream.LinkToFile("/shared/durable/"_dynamicBody.fileName)
        set sc=stream.CopyFromAndSave(dynamicStream)

        set imageVector = ..Checker("/shared/durable/"_dynamicBody.fileName)       
        set imageVector = $REPLACE(imageVector, $CHAR(13,10),",")
        set imageVector = $REPLACE(imageVector,"['","")
        set imageVector = $REPLACE(imageVector,"']","")
        set imageVector = $REPLACE(imageVector,"'","")
        set imageVector = $REPLACE(imageVector," ",",")

        set name = ""
        set similarity = ""
        &sql(SELECT TOP 1 name, similarity INTO :name, :similarity  FROM (SELECT name, VECTOR_DOT_PRODUCT(photo, TO_VECTOR(:imageVector, DECIMAL)) AS similarity FROM Vectorface_Data.Person) ORDER BY similarity DESC)

        set result = {"name": "", "similarity":""}
        set result.name = name
        set result.similarity = similarity
        Do ##class(%REST.Impl).%WriteResponse(result.%ToJSON())

        Do ##class(%REST.Impl).%SetStatusCode("200")	
        
    } Catch (ex) {
        Do ##class(%REST.Impl).%SetStatusCode("400")
        return ex.DisplayString()
    }
    Quit $$$OK
}

The function is very similar, with the exception that we do not record the image that we are going to compare, but rather we use the generated vector to compare it with those registered in the database through an SQL query.

Testing the example

We are going to register a few people with their photos in IRIS, for example... all the General Secretaries of the Communist Party of the Soviet Union because... Who hasn't wanted to know which leader of the Soviet Union they look like?

Here we have an example of our POST call:

As you can see we have the fields that identify Brezhnev with his associated base64 photo. This is how it would look in our table with a vector column:

It's time to launch a test, let's see which Secretary General is most like me:

Creepy...it seems that Stalin is my evil twin...although the similarity is quite low, let's try a different photo of Chernenko, in this case the result should be much higher.

Indeed, here we have a much higher value for Chernenko (0.736), which we already had registered in our database.

Conclusion

The inclusion of the vector type and its associated searches opens up a world of opportunities based on exploiting vector-based AI models, I encourage you all to try it!

PS: My thanks to @Thomas Dyar who provided me with the information necessary to develop this example.

2 Comments
讨论 (2)2
登录或注册以继续