搜索​​​​

清除过滤器
文章
Michael Lei · 九月 20, 2023

基于IRISI对您的敏感数据进行令牌化/代币化

根据剑桥词典的解释,令牌化数据是“用令牌(=代表第一个数据的不同数据)替换隐私数据,以防止隐私信息被不被允许做的人看到”(https://dictionary.cambridge.org/pt/dicionario/ingles/tokenize)。如今,一些公司,尤其是金融和医疗保健领域的公司,正在将其数据令牌/代币化作为满足网络安全和数据隐私(GDPR、CCPA、HIPAA 和 LGPD)要求的重要策略。但是,为什么不使用加密呢?保护敏感数据的令牌化过程比数据加密更常用,原因如下: 更好的性能:在密集的操作处理中动态加密和解密数据会提高性能并需要更多的处理器能力。 测试:可以标记生产数据库并复制到测试数据库,并维护适合更真实的单元和功能测试的测试数据。 更好的安全性:如果黑客破解或获得密钥,所有加密数据都将可用,因为加密是一个可逆过程。令牌化过程是不可逆的。如果您需要从令牌化数据中获取原始数据,则需要维护一个安全且独立的数据库来链接到原始数据和令牌化数据。 令牌化架构 令牌化架构需要两个数据库:应用程序数据库(App DB)用于存储令牌化数据和来自业务的其他数据;令牌数据库(Token Database)用于存储原始值和令牌化值,因此当您需要时,您的应用程序可以获得原始值以向用户显示。还有一个 令牌生成器 REST API 用于标记敏感数据、存储到令牌数据库中并返回票证。应用程序将票据、令牌化数据和其他数据存储在应用程序数据库中。参见架构图: 分词器应用程序 了解它在令牌化应用程序中的工作原理: https://openexchange.intersystems.com/package/Tokenizator。 该应用程序是一个用于标记化的 REST API: 对任何数值显示为“*”号。示例:信用卡 4450 3456 1212 0050 至 4450 **** **** 0050。 任何真实的IP地址都是假值。示例:192.168.0.1 到 168.1.1.1。 任何人的数据都是假的。示例:地址为北京海淀的张三到地址为西藏拉萨的仓央嘉措。 任何数值为假数值。示例:300.00 到 320.00。 任何信用卡数据都是虚假的信用卡号码。示例:4450 3456 1212 0050 至 4250 2256 4512 5050。 任何值到哈希值。示例:dfgdgasdrrrdd123 的系统架构师。 正则表达式的任何值。示例:使用正则表达式规则 [AZ]{2}-\\d{5}-[az]{5} 将 EI-54105-tjfdk 转换为 AI-44102-ghdfg。 如果您需要任何其他选项,请在 github 项目上提交问题。 要对值进行标记并在之后获取原始值,请按照以下步骤操作: 打开您的 Postman 或从您的应用程序使用此 API。 使用 STARS、PERSON、NUMBER、CREDITCARD、HASH、IPADDRESS 和 REGEX 方法对此敏感数据样本创建 令牌化请求: 方法:POST 网址: http://localhost:8080/token/tokenize 正文(JSON): [ { "tokenType":"STARS", "originalValueString":"545049405679", "settings": { "starsPosition":"1", "starsQuantity":"4" } }, { "tokenType":"IPADDRESS", "originalValueString":"192.168.0.1", "settings": { "classType":"CLASS_B", "ipSize":"4" } }, { "tokenType":"PERSON", "originalValueString":"Yuri Marx Pereira Gomes", "settings": { "localeLanguage":"en", "localeCountry":"US", "withAddress":"true", "withEmail":"true" } }, { "tokenType":"NUMBER", "originalValueNumber":300.0, "settings": { "minRange":"100.0", "maxRange":"400.0" } }, { "tokenType":"CREDITCARD", "originalValueString":"4892879268763190", "settings": { "type":"VISA" } }, { "tokenType":"HASH", "originalValueString":"System Architect" }, { "tokenType":"REGEX", "originalValueString":"EI-54105-tjfdk", "settings": { "regex":"[A-Z]{2}-\\d{5}-[a-z]{5}" } } ] 查看结果。您将获得一个令牌化的数值 (tokenizedValueString) 并将其存储到本地数据库中。 从响应中复制票证(将其与令牌化化值一起存储到本地数据库中) 现在凭票证即可获得原数值。创建一个请求以使用票证获取原始值: 方法:获取 网址: http://localhost:8080/token/query-ticket/TICKET-VALUE-HERE 查看您的原始值 生成的所有令牌都存储到 InterSystems IRIS Cloud SQL 中,以便您能够可靠地获得原始值。 欢迎体验!
文章
Lilian Huang · 九月 7, 2023

Docker 简介 - 第 2 部分(Docker Compose、Docker File、Docker Volume)

您好!社区的各位老师, 在我的上一篇文章中,我们学习了以下主题: 什么是 Docker? Docker 的一些好处 Docker 是如何工作的? Docker 镜像 Docker容器 Docker 镜像存储库 InterSystems 的 Docker 镜像存储库 Docker安装 Docker 基本命令 使用 Docker 运行 IRIS 社区版 Docker 桌面图形用户界面 在本文中,我们将讨论以下主题: 使用 Docker Compose 文件( YAML 文件) Docker 文件的使用(用于构建 Docker 镜像) Docker 卷的使用 那么让我们开始吧。 1.使用Docker Compose文件( YAML文件) Docker Compose 是一款旨在帮助定义和共享多容器应用程序的工具。使用 Compose,我们可以创建一个 YAML 文件来定义服务,并且通过单个命令,我们可以启动或拆除所有内容。 使用 Compose 的一大优势是能够在文件中定义应用程序堆栈并将其保存在项目存储库的根目录中。您还可以让其他人轻松地为您的项目做出贡献。 他们只需要克隆您的存储库并启动撰写应用程序。 在我的上一篇文章中,我们使用下面提到的命令来创建并启动带有 InterSystems 社区镜像的容器: docker run -d -p 52773:52773 intersystemsdc/iris-community 此时,让我们修改此命令并添加容器名称、映射更多端口并设置重新启动选项: docker run -d -p 52773:52773 -p 53773:53773 -p 1972:1972 --name iris --restart=always intersystemsdc/iris-community 让我为您分解一下上述命令: # docker run command to create and start the container docker run # -d -an option used to start container in deattach mode -d # -p -an option is used to map the ports -p 52773:52773 -p 53773:53773 -p 1972:1972 # name of the container --name iris # set the restart option to always --restart=always # base image intersystemsdc/iris-community 创建撰写文件 在根文件夹中,创建一个名为-----100-----的文件,并写入上述命令,如下所示: #specify docker-compose version version: '3.6' #services/container details services: #Name of the container iris: #Base Image image: intersystemsdc/iris-community #set restart option restart: always #port mapping ports: - 55036 :1972 - 55037 :52773 - 53773 :53773 docker run 命令和 docker-compose 文件的映射如下所示:Docker-compose 文件快照如下所示: 为了运行 docker-compose 文件代码,我们将使用 docker-compose up 命令: docker-compose up -d -----101----- 或 -----102-----:在后台运行命令并将控制返回到终端的选项。 容器已启动。让我们运行“docker ps”命令来列出正在运行的容器 正如您所看到的,我们使用 docker-compose 文件得到了相同的结果。 创建并启动多个容器 在 docker-compose 的帮助下,我们不仅可以运行多个容器,还可以组织并向其添加更多命令。 例如,在下面的 docker-compose 文件中,我们运行 MongoDB 容器和 iris 容器: #specify docker-compose version version: '3.6' #services/container details services: #Name of the container iris: #Base Image image: intersystemsdc/iris-community #set restart option restart: always #port mapping ports: - 55036:1972 - 55037:52773 - 53773:53773 #start MongoDB container mongodb: image: mongo ports: - 27017:27017 让我们运行 docker-compose up 命令 MongoDB 和 iris 容器现已创建并启动。 2.Docker 文件 Docker可以通过读取-----103-----的指令来自动构建镜像。 -----103----- 是一个文本文档,其中包含用户可以在命令行上调用来组装图像的所有命令。 所以,我们的第一个问题很简单。什么是 Dockerfile? Docker 使用它来构建镜像本身。 Dockerfile 本质上是如何创建镜像的构建指令。 与简单存储二进制映像相比,Dockerfile 的优点是自动构建将确保您拥有可用的最新版本。从安全角度来看这是一件好事,因为您希望确保没有安装任何易受攻击的软件。 常用 Docker 文件命令 您可以在下面找到一些最常用的 docker 命令。请注意,所有 docker 命令都必须大写字母。 从 第一个是 FROM 命令,它告诉您映像基于什么。正是这种多层方法使得 Docker 如此高效和强大。在本例中,使用了 iris-community Docker 映像,它再次引用 Dockerfile 来自动化构建过程。 FROM intersystemsdc/iris-community 工作目录 该命令用于设置一个工作目录,我们将在其中复制文件。例如,下面提到的命令将设置 /opt/irisbuild 作为工作目录: WORKDIR /opt/irisbuild 复制 COPY 命令就像听起来一样简单。它可以将文件复制到容器中。通常,我们复制自定义配置文件、应用程序源文件、数据文件等。 #coping Installer.cls to a root of workdir. Don't miss the dot, here. COPY Installer.cls . #copy source files from src folder to src folder in workdir in the docker container. COPY src src #copy source files from data/fhir folder to fhirdata folder in the docker container. COPY data/fhir fhirdata 环境电压 这会设置环境变量,这些变量可以在 Dockerfile 及其调用的任何脚本中使用。-----105-----指令将环境变量-----106-----定义为值-----107----- ENV USER_ID "SYSTEM" ENV USER_PASSWORD "MANAGER" 跑步 -----108-----命令用于在镜像构建过程中执行命令。 #here we give the rights to irisowner user and group which are run IRIS. RUN chown ${ISC_PACKAGE_MGRUSER} : ${ISC_PACKAGE_IRISGROUP} /opt/irisapp #start IRIS and run script in iris.script file RUN iris start IRIS \ && iris session IRIS < /tmp/iris.script 用户 默认情况下,容器以 root 身份运行,这使它们能够完全控制主机系统。随着容器技术的成熟,可能会出现更安全的默认选项。目前,要求 root 对其他人来说是危险的,并且可能不适用于所有环境。您的映像应使用 -----109----- 指令来指定容器运行的非 root用户。如果您的软件没有创建自己的用户,您可以在 Dockerfile 中创建用户和组。 #here we switch user to a root to create a folder and copy files in docker. USER root WORKDIR /opt/irisapp #switching user from root to irisowner, to copy files USER irisowner COPY src src 更多细节请阅读Docker官方文档 3.Docker卷 Docker卷是一个完全由Docker管理的独立文件系统。它作为标准文件或目录存在于数据保存的主机上。 使用 Docker 卷的目的是将数据保留在容器外部,以便可用于备份或共享。 Docker 卷依赖于 Docker 的文件系统,是 Docker 容器和服务保存数据的首选方法。当容器启动时,Docker 会加载只读镜像层,在镜像堆栈顶部添加读写层,并将卷挂载到容器文件系统上。 我们使用 -----110----- 或 -----111----- 标志来允许我们将本地文件挂载到容器中。 卷是保存 Docker 容器生成和使用的数据的首选机制。虽然绑定挂载取决于主机的目录结构和操作系统,但卷完全由 Docker 管理。与绑定挂载相比,卷有几个优点: 卷比绑定安装更容易备份或迁移。 您可以使用 Docker CLI 命令或 Docker API 管理卷。 卷适用于 Linux 和 Windows 容器。 卷可以在多个容器之间更安全地共享。 卷驱动程序允许您将卷存储在远程主机或云提供商上,以加密卷的内容或添加其他功能。 新卷的内容可以由容器预先填充。 Docker Desktop 上的卷比 Mac 和 Windows 主机上的绑定挂载具有更高的性能。 此外,卷通常是比将数据保留在容器的可写层中更好的选择,因为卷在使用时不会增加容器的大小。此外,卷的内容存在于给定容器的生命周期之外。 我们可以在 docker-compose 文件的 services 部分下提及卷。 #specify docker-compose version version: '3.6' #services/container details services: #Name of the container iris: #Base Image image: intersystemsdc/iris-community #set restart option restart: always #port mapping ports: - 55036 :1972 - 55037 :52773 - 53773 :53773 #create a volume volumes: - ./:/irisdev/app 我们已经创建了 irisdev/app 卷。 概括 Docker 是一个功能强大的工具,允许开发人员和 IT 团队在容器化环境中创建、部署和运行应用程序。通过提供可移植性、一致性、可扩展性、资源效率和安全性,Docker 可以轻松地跨不同环境和基础设施部署应用程序。随着容器化的日益普及,Docker正在成为现代软件开发和部署的重要工具。在本文中,我们学习了如何使用 Docker compose(一个 YAML 文件,指定应用程序中每个容器的配置选项)、Docker 文件(用于构建 Docker 镜像)和 Docker 卷(一种用于共享数据的持久数据存储机制) Docker 容器和主机之间的数据。) 感谢您的阅读!
文章
Jingwei Wang · 二月 15

使用嵌入式 Python 和 OpenAI API 在 IRIS 中进行数据标签

大型语言模型(例如 OpenAI 的 GPT-4)的发明和普及掀起了一波创新解决方案浪潮,这些解决方案可以利用大量非结构化数据,在此之前,人工处理这些数据是不切实际的,甚至是不可能的。此类应用程序可能包括数据检索(请参阅 Don Woodlock 的 ML301 课程,了解检索增强生成的精彩介绍)、情感分析,甚至完全自主的 AI 代理等! 在本文中,我想演示如何使用 IRIS 的嵌入式 Python 功能直接与 Python OpenAI 库交互,方法是构建一个简单的数据标记应用程序,该应用程序将自动为我们插入IRIS 表中的记录分配关键字。然后,这些关键字可用于搜索和分类数据,以及用于数据分析目的。我将使用客户对产品的评论作为示例用例。 先决条件 运行的IRIS实例 OpenAI API 密钥(您可以在此处创建) 配置好的开发环境(本文将使用VS Code ) Review类 让我们首先创建一个 ObjectScript 类,该类将定义客户评论的数据模型。为了简单起见,我们将只定义 4 个 %String 字段:客户姓名、产品名称、评论正文以及我们将生成的关键字。该类应该扩展%Persistent,以便我们可以将其对象保存到磁盘。 Class DataTagging.Review Extends %Persistent { Property Name As %String(MAXLEN = 50) [ Required ]; Property Product As %String(MAXLEN = 50) [ Required ]; Property ReviewBody As %String(MAXLEN = 300) [ Required ]; Property Keywords As %String(MAXLEN = 300) [ SqlComputed, SqlComputeOnChange = ReviewBody ]; } 由于我们希望在插入或更新 ReviewBody 属性时自动计算 Keywords属性,因此我将其标记为SqlComputed。您可以在此处了解有关计算值的更多信息。 KeywordsComputation方法 我们现在想要定义一种方法,用于根据ReviewBody计算Keywords。我们可以使用Embedded Python直接与官方的openai Python包进行交互。但首先,我们需要安装它。为此,请运行以下 shell 命令: <your-IRIS-installation-path>/bin/irispip install --target <your-IRIS-installation-path>/Mgr/python openai 我们现在可以使用 OpenAI 的聊天完成 API 来生成关键字: ClassMethod KeywordsComputation(cols As %Library.PropertyHelper) As %String [ Language = python ] { ''' This method is used to compute the value of the Keywords property by calling the OpenAI API to generate a list of keywords based on the review body. ''' from openai import OpenAI client = OpenAI( # Defaults to os.environ.get("OPENAI_API_KEY") api_key="<your-api-key>", ) # Set the prompt; use few-shot learning to give examples of the desired output user_prompt = "Generate a list of keywords that summarize the content of a customer review of a product. " \ + "Output a JSON array of strings.\n\n" \ + "Excellent watch. I got the blue version and love the color. The battery life could've been better though.\n\nKeywords:\n" \ + "[\"Color\", \"Battery\"]\n\n" \ + "Ordered the shoes. The delivery was quick and the quality of the material is terrific!.\n\nKeywords:\n" \ + "[\"Delivery\", \"Quality\", \"Material\"]\n\n" \ + cols.getfield("ReviewBody") + "\n\nKeywords:" # Call the OpenAI API to generate the keywords chat_completion = client.chat.completions.create( model="gpt-4", # Change this to use a different model messages=[ { "role": "user", "content": user_prompt } ], temperature=0.5, # Controls how "creative" the model is max_tokens=1024, # Controls the maximum number of tokens to generate ) # Return the array of keywords as a JSON string return chat_completion.choices[0].message.content } 请注意,在提示中,我首先指定了我希望 GPT-4 如何“生成总结产品客户评论内容的关键字列表”的一般说明,然后给出两个示例输入以及所需的输入输出。然后,我插入 cols.getfield("ReviewBody") 并以“Keywords:”一词结束提示,通过提供与我给出的示例格式相同的关键字来推动它完成句子。这是Few-Shot Prompting技术的一个简单示例。 为了演示的简单性,我选择将关键字存储为 JSON 字符串;在生产中存储它们的更好方法可能是DynamicArray ,但我将把它作为练习留给读者。 关键词生成 现在,我们可以通过管理门户使用以下 SQL 脚本向表中插入一行来测试我们的数据标记应用程序: INSERT INTO DataTagging.Review (Name, Product, ReviewBody) VALUES ('Ivan', 'BMW 330i', 'Solid car overall. Had some engine problems but got everything fixed under the warranty.') 如下所示,它自动为我们生成了四个关键字。做得好! 结论 总而言之,InterSystems IRIS 嵌入 Python 的能力在处理非结构化数据时提供了多种可能性。利用 OpenAI 的强大功能进行自动数据标记只是利用这一强大功能可以实现的目标之一。这可以减少人为错误并提高整体效率。
文章
Kelly Huang · 九月 3, 2023

独立模式下 EMPI 的安装和适配 - FHIR之转换和摄取

大家好。 在上一篇文章中,我们了解了如何配置 EMPI 来接收 FHIR 消息。为此,我们安装了 InterSystems 提供的 FHIR 适配器,该适配器配置了一个可以向其发送 FHIR 消息的 REST 端点。然后,我们将获取消息并将其转换为 %String,我们将通过 TCP 将其发送到 HSPIDATA 命名空间中配置的 EMPI 的输出。 好吧,是时候看看我们如何检索消息、将其转换回 %DynamicObject 并将其解析为 EMPI 用来存储信息的类。 TCP消息接收 正如我们所指出的,从配置了 FHIR 资源接收的生产中,我们已将消息发送到我们有业务服务侦听的特定 TCP 端口,在我们的例子中,该业务服务将是一个简单的EnsLib.TCP。 PassthroughService的目标是捕获消息并将其转发到业务流程,我们将在其中执行所需的数据转换。 这里有我们的商业服务: 这是它的基本配置: FHIR 消息的转变 正如你所看到的,我们只配置了通过 TCP 接收消息的端口以及我们将向其发送消息的组件,在我们的例子中我们将其称为 Local.BP.FHIRProcess,让我们看一下说类来看看我们如何从 FHIR 资源中检索信息: Class Local.BP.FHIRProcess Extends Ens.BusinessProcess [ ClassType = persistent ] { Method OnRequest(pRequest As Ens.StreamContainer, Output pResponse As Ens.Response) As %Status { set tDynObj = {}. %FromJSON (pRequest.Stream) If (tDynObj '= "" ) { set hubRequest = ##class (HS.Message.AddUpdateHubRequest). %New () // Create AddUpdateHub Message // Name, sex, DOB set givenIter = tDynObj.name. %Get ( 0 ).given. %GetIterator () while givenIter. %GetNext (, .givenName){ if (hubRequest.FirstName '= "" ) { Set hubRequest.FirstName=givenName } else { Set hubRequest.FirstName=hubRequest.FirstName_ " " _givenName } } Set hubRequest.FirstName=tDynObj.name. %Get ( 0 ).given. %Get ( 0 ) Set hubRequest.LastName=tDynObj.name. %Get ( 0 ).family Set hubRequest.Sex=tDynObj.gender Set hubRequest.DOB=hubRequest.DOBDisplayToLogical(tDynObj.birthDate) // Inserts full birth name information for the patient set nameIter = tDynObj.name. %GetIterator () while nameIter. %GetNext (, .name){ Set tName = ##class (HS.Types.PersonName). %New () if (name.prefix '= "" ) { Set tName.Prefix = name.prefix. %Get ( 0 ) } Set tName.Given = name.given. %Get ( 0 ) Set tName.Middle = "" Set tName.Family = name.family Set tName.Suffix = "" Set tName.Type= ^Ens .LookupTable( "TypeOfName" ,name. use ) Do hubRequest.Names.Insert(tName) } set identIter = tDynObj.identifier. %GetIterator () while identIter. %GetNext (, .identifier){ if (identifier.type'= "" ){ if (identifier.type.coding. %Get ( 0 ).code = "MR" ) { Set hubRequest.MRN = identifier.value Set hubRequest.AssigningAuthority = ^Ens .LookupTable( "hospital" ,identifier.system) Set hubRequest.Facility = ^Ens .LookupTable( "hospital" ,identifier.system) } elseif (identifier.type.coding. %Get ( 0 ).code = "SS" ) { Set hubRequest.SSN = identifier.value } else { Set tIdent= ##class (HS.Types.Identifier). %New () Set tIdent.Root = identifier.system // refers to an Assigning Authority entry in the OID Registry Set tIdent.Extension = identifier.value Set tIdent.AssigningAuthorityName = identifier.system Set tIdent. Use = identifier.type.coding. %Get ( 0 ).code Do hubRequest.Identifiers.Insert(tIdent) } } } // Address set addressIter = tDynObj.address. %GetIterator () while addressIter. %GetNext (, .address){ Set addr= ##class (HS.Types.Address). %New () Set addr.City=address.city Set addr.State=address.state Set addr.Country=address.country Set addr.StreetLine=address.line. %Get ( 0 ) Do hubRequest.Addresses.Insert(addr) } //Telephone set identTel = tDynObj.telecom. %GetIterator () while identTel. %GetNext (, .telecom){ if (telecom.system = "phone" ) { Set tel= ##class (HS.Types.Telecom). %New () Set tel.PhoneNumber=telecom.value Do hubRequest.Telecoms.Insert(tel) } } } Set tSC = ..SendRequestSync ( "HS.Hub.MPI.Manager" , hubRequest, .pResponse) Quit tSC } Storage Default { <Type> %Storage.Persistent </Type> } } 让我们更详细地看看我们正在做什么: 首先我们收到了业务服务发来的消息: Method OnRequest(pRequest As Ens.StreamContainer, Output pResponse As Ens.Response) As %Status { set tDynObj = {}. %FromJSON (pRequest.Stream) 正如我们在 OnRequest 方法的签名中看到的,输入消息对应于Ens.StreamContainer类型的类。 %String 类型消息的这种转换已在业务服务中进行。在该方法的第一行中,我们要做的是检索在 pRequest 变量中作为 Stream 找到的消息。然后,我们使用 %FromJSON 语句将其转换为 %DynamicObject。 通过将消息映射到动态对象,我们将能够访问已发送的 FHIR 资源的每个字段: set tDynObj = {}. %FromJSON (pRequest.Stream) If (tDynObj '= "" ) { set hubRequest = ##class (HS.Message.AddUpdateHubRequest). %New () // Create AddUpdateHub Message // Name, sex, DOB set givenIter = tDynObj.name. %Get ( 0 ).given. %GetIterator () while givenIter. %GetNext (, .givenName){ if (hubRequest.FirstName '= "" ) { Set hubRequest.FirstName=givenName } else { Set hubRequest.FirstName=hubRequest.FirstName_ " " _givenName } } Set hubRequest.FirstName=tDynObj.name. %Get ( 0 ).given. %Get ( 0 ) Set hubRequest.LastName=tDynObj.name. %Get ( 0 ).family Set hubRequest.Sex=tDynObj.gender Set hubRequest.DOB=hubRequest.DOBDisplayToLogical(tDynObj.birthDate) 在此片段中,我们看到如何创建HS.Message.AddUpdateHubRequest类的对象,该对象是我们将发送到负责在 EMPI 内执行相应操作的业务操作 HS.Hub.MPI.Manager 的对象,无论是是创建新患者或更新它,以及将其与 EMPI 中已有的其他患者可能存在的可能匹配项链接起来。 下一步是使用从业务服务接收到的数据填充新对象。正如您所看到的,我们所做的就是从刚刚创建的动态对象的不同字段中检索数据。动态对象的格式与 HL7 FHIR 为患者资源定义的格式完全对应,您可以直接在HL7 FHIR 网页上查看示例 对于我们的示例,我们从 HL7 FHIR 页面本身提供的列表中选择了该患者: { "resourceType" : "Patient" , "id" : "example" , "text" : { "status" : "generated" , "div" : "<div xmlns=\"http://www.w3.org/1999/xhtml\">\n\t\t\t<table>\n\t\t\t\t<tbody>\n\t\t\t\t\t<tr>\n\t\t\t\t\t\t<td>Name</td>\n\t\t\t\t\t\t<td>Peter James \n <b>Chalmers</b> ("Jim")\n </td>\n\t\t\t\t\t</tr>\n\t\t\t\t\t<tr>\n\t\t\t\t\t\t<td>Address</td>\n\t\t\t\t\t\t<td>534 Erewhon, Pleasantville, Vic, 3999</td>\n\t\t\t\t\t</tr>\n\t\t\t\t\t<tr>\n\t\t\t\t\t\t<td>Contacts</td>\n\t\t\t\t\t\t<td>Home: unknown. Work: (03) 5555 6473</td>\n\t\t\t\t\t</tr>\n\t\t\t\t\t<tr>\n\t\t\t\t\t\t<td>Id</td>\n\t\t\t\t\t\t<td>MRN: 12345 (Acme Healthcare)</td>\n\t\t\t\t\t</tr>\n\t\t\t\t</tbody>\n\t\t\t</table>\n\t\t</div>" }, "identifier" : [ { "use" : "usual" , "type" : { "coding" : [ { "system" : "http://terminology.hl7.org/CodeSystem/v2-0203" , "code" : "MR" } ] }, "system" : "urn:oid:1.2.36.146.595.217.0.1" , "value" : "12345" , "period" : { "start" : "2001-05-06" }, "assigner" : { "display" : "Acme Healthcare" } } ], "active" : true , "name" : [ { "use" : "official" , "family" : "Chalmers" , "given" : [ "Peter" , "James" ] }, { "use" : "usual" , "given" : [ "Jim" ] }, { "use" : "maiden" , "family" : "Windsor" , "given" : [ "Peter" , "James" ], "period" : { "end" : "2002" } } ], "telecom" : [ { "use" : "home" }, { "system" : "phone" , "value" : "(03) 5555 6473" , "use" : "work" , "rank" : 1 }, { "system" : "phone" , "value" : "(03) 3410 5613" , "use" : "mobile" , "rank" : 2 }, { "system" : "phone" , "value" : "(03) 5555 8834" , "use" : "old" , "period" : { "end" : "2014" } } ], "gender" : "male" , "birthDate" : "1974-12-25" , "_birthDate" : { "extension" : [ { "url" : "http://hl7.org/fhir/StructureDefinition/patient-birthTime" , "valueDateTime" : "1974-12-25T14:35:45-05:00" } ] }, "deceasedBoolean" : false , "address" : [ { "use" : "home" , "type" : "both" , "text" : "534 Erewhon St PeasantVille, Rainbow, Vic 3999" , "line" : [ "534 Erewhon St" ], "city" : "PleasantVille" , "district" : "Rainbow" , "state" : "Vic" , "postalCode" : "3999" , "period" : { "start" : "1974-12-25" } } ], "contact" : [ { "relationship" : [ { "coding" : [ { "system" : "http://terminology.hl7.org/CodeSystem/v2-0131" , "code" : "N" } ] } ], "name" : { "family" : "du Marché" , "_family" : { "extension" : [ { "url" : "http://hl7.org/fhir/StructureDefinition/humanname-own-prefix" , "valueString" : "VV" } ] }, "given" : [ "Bénédicte" ] }, "telecom" : [ { "system" : "phone" , "value" : "+33 (237) 998327" } ], "address" : { "use" : "home" , "type" : "both" , "line" : [ "534 Erewhon St" ], "city" : "PleasantVille" , "district" : "Rainbow" , "state" : "Vic" , "postalCode" : "3999" , "period" : { "start" : "1974-12-25" } }, "gender" : "female" , "period" : { "start" : "2012" } } ], "managingOrganization" : { "reference" : "Organization/1" } } 首先,我们创建了 2 个查找表,用于映射姓名类型和分配医疗记录号 (MR) 的权限,第一个与 EMPI 管理的类型兼容,第二个用于识别分配权限生成标识符: Set tName.Type= ^Ens .LookupTable( "TypeOfName" ,name. use ) Set hubRequest.AssigningAuthority = ^Ens .LookupTable( "hospital" ,identifier.system) Set hubRequest.Facility = ^Ens .LookupTable( "hospital" ,identifier.system) 启动测试消息 完美,让我们针对我们在上一篇文章中定义的端点启动 FHIR 消息: 正如您所看到的,我们收到了 200 响应,这仅意味着 EMPI 已正确接收到消息,现在让我们看看在我们的生产中生成的跟踪: 这里我们有我们的病人,您可以看到转换已成功执行,并且 FHIR 消息中报告的所有字段都已正确分配。可以看到,一条IDUpdateNotificationRequest通知消息已经生成了。当在系统中执行创建或更新患者的操作时,会生成此类通知。 很好,让我们通过按姓名搜索患者来检查患者是否在我们的系统中正确注册: 答对了!让我们更详细地看看我们亲爱的Peter的数据: 相当完美!我们的 EMPI 中已经包含了有关患者的所有必要信息。正如您所看到的,该机制非常简单,让我们回顾一下我们执行的步骤: 我们已将 InterSystems 提供的 FHIR 适配器工具安装在配置为支持互操作性的命名空间(与 EMPI 独立安装生成的命名空间不同的命名空间,在我的例子中称为 WEBINAR)中。 我们在此命名空间中创建了一个业务操作,它将接收到的HS.FHIRServer.Interop.Request类型的消息转换为 %String,并将其发送到在 EMPI 命名空间 (HSPIDATA) 的生产中配置的业务服务。 接下来,我们添加了EnsLib.TCP.PassthroughService类的业务服务,该类接收从 WEBINAR 命名空间的生成发送的消息并重定向到业务流程Local.BP.FHIRProcess 。 在 BP Local.BP.FHIRProcess 中,我们已将接收到的 Stream 转换为HS.Message.AddUpdateHubRequest类型的对象,并将其发送到业务运营HS.Hub.MPI.Manager ,该管理器将负责将其注册到我们的EMPI。 正如您所看到的,EMPI 功能与 IRIS 集成引擎提供的功能的结合使我们能够使用几乎任何类型的技术。 我希望这篇文章对您有用。如果您有任何问题或建议,您已经知道,请发表评论,我将很乐意为您解答。 原贴作者:@Luis Angel
文章
Lilian Huang · 七月 9, 2023

从 IRIS 嵌入式 Python 动态创建 HL7 消息

#Embedded Python #HL7 #InterSystems IRIS for Health 写在回复社区帖子《Python能否动态创建HL7消息》中。 前提条件和设置 使用一个启用了集成的命名空间。注意:USER命名空间默认不启用互操作性。如果以下建议创建一个新的互操作性命名空间来探索功能。 # 切换到ZN "[互操作性名称空间名称]" # 启动交互式Python shell:Do $SYSTEM.Python.Shell() 启动脚本 #Load dependencies import datetime as dt import uuid # Cache current time in CCYYMMDDHHMMss format hl7_datetime_now=dt.datetime.now().strftime('%Y%m%d%H%M%S') # Create HL7 Message hl7=iris.cls("EnsLib.HL7.Message")._New() # Set the doc type # 2.5.1:ORU_R01 - Unsolicited transmission of an observation message hl7.PokeDocType("2.5.1:ORU_R01") 这些信息的结构可以从管理门户中获取 创建MSH(消息头段)。 // MSH Segment hl7.SetValueAt('OutApp','MSH:SendingApplication') hl7.SetValueAt('OutFac','MSH:SendingFacility') hl7.SetValueAt('InApp','MSH:ReceivingApplication') hl7.SetValueAt('InFac','MSH:ReceivingFacility') hl7.SetValueAt(hl7_datetime_now,'MSH:DateTimeOfMessage') hl7.SetValueAt('ORU','MSH:MessageType.MessageCode') hl7.SetValueAt('R01','MSH:MessageType.TriggerEvent') hl7.SetValueAt('ORU_R01','MSH:MessageType.MessageStructure') hl7.SetValueAt(str(uuid.uuid4()),'MSH:MessageControlID') hl7.SetValueAt('2.5.1','MSH:ProcessingID') 编码和解码 HL7文件被格式化为段每个段被分隔符("|")和重复元素("~")划分为多个元素在一个元素内有"^"分界符和"&"子分界符。当定界符作为实际的文本内容出现时,它将被"\"和其他取代定界符的字符转义。通常,"&"是有问题的,因为它可能经常出现在信息中,导致接收系统读取时出现截断现象。HL7段有一个内置的方法,用于根据当前为信息选择的定界符来转义内容。一个常见的模式是获得对第一个段的引用 # Do this line the variable "msh" is used later > msh=hl7.GetSegmentAt(1) 然后可以调用Escape,例如用Python的原始字符串: > msh.Escape(r"a&b~c^d") 'a\\T\\b\\R\\c\\S\\d' The segment can also be used to Unescape back for example: > msh.Unescape('a\\T\\b\\R\\c\\S\\d') 'a&b~c^d' 因此,在设置预计包含分隔符的内容时,可以为信息转义这些分隔符 hl7.SetValueAt(msh.Escape(r"a&b~c^d"),'MSH:ReceivingFacility') 检索内容时可以不加转义 msh.Unescape(hl7.GetValueAt('MSH:ReceivingFacility')) 在这个例子中,只是将msh重新设置为以前的值 hl7.SetValueAt('InFac','MSH:ReceivingFacility') 仔细检查到目前为止的部分: > hl7.GetValueAt('MSH') 'MSH|^~\\&|OutApp|OutFac|InApp|InFac|20230610100040||ORU^R01^ORU_R01|2dfab415-51aa-4c75-a7e7-a63aedfb53cc|2.5.1' 人口统计学(PID)部分 # Virtual path prefix for PID seg='PIDgrpgrp(1).PIDgrp.PID:' hl7.SetValueAt('1',seg+'SetIDPID') hl7.SetValueAt('12345',seg+'PatientIdentifierList(1).IDNumber') hl7.SetValueAt('MRN',seg+'PatientIdentifierList(1).AssigningAuthority') hl7.SetValueAt('MR',seg+'PatientIdentifierList(1).IdentifierTypeCode') hl7.SetValueAt(msh.Escape('Redfield'), seg+'PatientName(1).FamilyName') hl7.SetValueAt(msh.Escape('Claire') ,seg+'PatientName(1).GivenName') hl7.SetValueAt('19640101',seg+'DateTimeofBirth') hl7.SetValueAt('F',seg+'AdministrativeSex') hl7.SetValueAt(msh.Escape('Umbrella Corporation') ,seg+'PatientAddress.StreetAddress') hl7.SetValueAt(msh.Escape('Umbrella Drive') ,seg+'PatientAddress.OtherDesignation') hl7.SetValueAt(msh.Escape('Raccoon City') ,seg+'PatientAddress.City') hl7.SetValueAt(msh.Escape('MO') ,seg+'PatientAddress.StateorProvince') hl7.SetValueAt(msh.Escape('63117') ,seg+'PatientAddress.ZiporPostalCode') 仔细检查PID段的内容 > hl7.GetValueAt(seg[0:-1]) 'PID|1||12345^^^MRN^MR||Redfield^Claire||19640101|F|||Umbrella Corporation^Umbrella Drive^Raccoon City^MO^63117' 订单控制部分 seg='PIDgrpgrp(1).ORCgrp(1).ORC:' hl7.SetValueAt('RE',seg+'OrderControl') hl7.SetValueAt('10003681',seg+'PlacerOrderNumber') hl7.SetValueAt('99001725',seg+'FillerOrderNumber') hl7.SetValueAt('AG104',seg+'OrderingProvider') hl7.SetValueAt('L43',seg+'EnterersLocation') 仔细检查ORC部分的内容 > hl7.GetValueAt(seg[0:-1]) 'ORC|RE|10003681|99001725|||||||||AG104|L43' 观察请求 seg='PIDgrpgrp(1).ORCgrp(1).OBR:' hl7.SetValueAt('1',seg+'SetIDOBR') hl7.SetValueAt('10003681',seg+'PlacerOrderNumber') hl7.SetValueAt('99001725',seg+'FillerOrderNumber') hl7.SetValueAt('20210428100729',seg+'ResultsRptStatusChngDateTime') hl7.SetValueAt('F',seg+'ResultStatus') hl7.SetValueAt('U',seg+'QuantityTiming.Priority') OBX 观察/结果 seg='PIDgrpgrp(1).ORCgrp(1).OBXgrp(1).OBX:' hl7.SetValueAt('1',seg+'SetIDOBX') hl7.SetValueAt('TX',seg+'ValueType') hl7.SetValueAt('V8132',seg+'ObservationIdentifier.Identifier') hl7.SetValueAt(msh.Escape('G-Virus') , seg+'ObservationIdentifier.Identifier') hl7.SetValueAt(msh.Escape('17.8 log10') ,seg+'ObservationValue') hl7.SetValueAt(msh.Escape('RNA copies/mL') ,seg+'Units') hl7.SetValueAt('F',seg+'ObservationResultStatus') hl7.SetValueAt('20210428100729',seg+'DateTimeoftheObservation') hl7.SetValueAt('AG001',seg+'ResponsibleObserver.IDNumber') hl7.SetValueAt('Birkin',seg+'ResponsibleObserver.FamilyName') hl7.SetValueAt('William',seg+'ResponsibleObserver.GivenName') hl7.SetValueAt('AG001',seg+'ResponsibleObserver.IDNumber') hl7.SetValueAt('UXL43',seg+'EquipmentInstanceIdentifier') NTE - 注释和评论 seg='PIDgrpgrp(1).ORCgrp(1).OBXgrp(1).NTE(1):' hl7.SetValueAt('1',seg+'SetIDNTE') hl7.SetValueAt(msh.Escape('Expected late onset Hyphema. Contain but do not approach.') ,seg+'Comment') 向终端打印全部信息 > print(hl7.OutputToString()) MSH|^~\&|OutApp|OutFac|InApp|InFac|20230610141201||ORU^R01^ORU_R01|2dfab415-51aa-4c75-a7e7-a63aedfb53cc|2.5.1 PID|1||12345^^^MRN^MR||Redfield^Claire||19640101|F|||Umbrella Corporation^Umbrella Drive^Raccoon City^MO^63117 ORC|RE|10003681|99001725|||||||||AG104|L43 OBR|1|10003681|99001725|||||||||||||||||||20210428100729|||F||^^^^^U OBX|1|TX|G-Virus||17.8 log10|RNA copies/mL|||||F|||20210428100729||AG001^Birkin^William||UXL43 NTE|1||Expected late onset Hyphema. Contain but do not approach. 陷阱 如果一个元素的内容包含一个诸如 "8@%SYS.Python "的值,很可能是需要用字符串值或字符串属性来代替。 例如,uuid在MSH结构中被 "str "包裹着。 原文请查看 来自 Alex Woodhead https://community.intersystems.com/post/dynamically-creating-hl7-message-iris-embedded-python
文章
姚 鑫 · 六月 4, 2023

第二十四章 开发Productions - ObjectScript Productions - 定义业务服务

# 第二十四章 开发Productions - ObjectScript Productions - 定义业务服务 本页介绍如何定义业务服务类。 提示: `IRIS® `提供使用特定入站适配器的专用业务服务类,其中之一可能适合需要。如果是这样,则不需要编程。有关部分列表,请参阅 `Introducing Interoperability Productions` 中的连接选项。 # 介绍 业务服务负责接受来自外部应用程序的请求到 `IRIS`。下图显示了它是如何工作的: 请注意,此图仅显示数据的输入流,而不是可选响应。 业务服务负责以下活动: - 等待特定的外部事件(例如来自应用程序的通知、收到 `TCP` 消息等)。 - 读取、解析和验证伴随此类事件的数据, - 如果需要,返回对外部应用程序的确认,表明已收到事件。 - 创建请求消息的实例并将其转发到适当的业务流程或业务操作以进行处理。 业务服务的目的通常是接收数据输入。在大多数情况下,业务服务有一个与之关联的入站适配器。但是,在某些情况下不需要适配器,因为应用程序能够将请求消息发送到服务中,或者因为业务服务已被编写为处理特定类型的外部调用,例如来自复合应用程序的调用。这种类型的业务服务称为无适配器业务服务。 当业务服务具有入站适配器时,它处于数据拉取(而不是推送)模式。在这种模式下,业务服务会定期轮询适配器,看它是否有数据。同时,如果适配器随时遇到输入数据,它会调用业务服务来处理输入。 当业务服务没有适配器时,它不会拉取数据。相反,客户端应用程序调用业务服务并告诉它处理输入(这是一种数据推送模式)。 # 关键原则 首先,务必阅读 `Programming in InterSystems IRIS`。 在业务服务中,可以访问关联适配器的属性和方法,这些适配器作为业务服务的 Adapter 属性提供。这意味着可以更改适配器的默认行为;这样做可能合适也可能不合适。记住封装原则很有用。封装的思想是适配器类应该负责技术特定的逻辑,而业务服务类应该负责生产特定的逻辑。 如果发现有必要在业务服务类中大量或频繁地改变适配器类的行为,那么创建适配器类的自定义子类可能更合适。请参阅不太常见的任务。 这个原则也适用于商业运作。 # 定义业务服务类 要创建一个业务服务类,定义一个类如下: - 类必须在(或子类)中扩展 `Ens.BusinessService`。 - 在类中,`ADAPTER` 参数必须等于此业务服务要使用的适配器类的名称。 提示:如果只是希望业务服务定期唤醒和运行而不关心 `IRIS` 外部的事件,请使用适配器类 `Ens.InboundAdapter`。 - 类必须实现 `OnProcessInput()` 方法,如实现 `OnProcessInput()` 方法中所述。 - 类可以添加或删除设置。请参阅添加和删除设置。 - 类可以实现任何或所有启动和拆卸方法。请参阅覆盖启动和停止行为。 - 类可以包含完成自身内部工作的方法。 有关业务服务类的示例,请参阅适配器指南。 # 实施 `OnProcessInput()` 方法 在业务服务类中, `OnProcessInput()` 方法可以具有以下通用签名: ```java Method OnProcessInput(pInput As %RegisteredObject, pOutput As %RegisteredObject) As %Status ``` 这里的`pInput`是适配器要发送给这个业务服务的输入对象,`pOutput`是输出对象。 首先查看选择的适配器类。 建议编辑 `OnProcessInput()` 方法签名以使用适配器所需的特定输入参数。 `OnProcessInput()` 方法应该执行以下部分或全部操作: 1. 可选地设置业务服务类的属性(在任何适当的时间)。最受关注的业务服务属性是 `%WaitForNextCallInterval`。它的值控制 `IRIS` 调用适配器的 `OnTask()` 方法的频率。 有关其他属性,请参阅 `Ens.BusinessService`的类参考。 2. 如有必要,验证输入对象。 3. 检查输入对象并决定如何使用它。 4. 创建请求消息类的实例,这将是业务服务发送的消息。 5. 对于请求消息,使用输入对象中的值适当地设置其属性。 6. 确定要将请求消息发送到哪里。当发送消息时,将需要在生产中使用业务主机的配置名称。 7. 将请求消息发送到生产(业务流程或业务操作)中的目的地。请参阅下一节。 8. 确保设置输出参数 (`pOutput`)。通常,将其设置为等于您收到的响应消息。此步骤是必需的。 9. 返回适当的状态。此步骤是必需的。
文章
Kelly Huang · 七月 12, 2023

当 GPT 与 FHIR 碰撞出火花:利用Open API 的规范力量

FHIR 通过提供标准化数据模型来构建医疗保健应用程序并促进不同医疗保健系统之间的数据交换,彻底改变了医疗保健行业。由于 FHIR 标准基于现代 API 驱动的方法,因此移动和 Web 开发人员更容易使用它。然而,与 FHIR API 交互仍然具有挑战性,尤其是在使用自然语言查询数据时。 隆重推出FHIR - AI 和 OpenAPI 链应用程序,该解决方案允许用户使用自然语言查询与 FHIR API 进行交互。该应用程序使用OpenAI 、 LangChain和Streamlit构建,简化了查询 FHIR API 的过程并使其更加用户友好。 FHIR OpenAPI 规范是什么? OpenAPI 规范(以前称为 Swagger,目前是OpenAPI Initiative的一部分)已成为软件开发领域的重要工具,使开发人员能够更有效地设计、记录 API 并与 API 交互。 OpenAPI 规范定义了一种标准的机器可读格式来描述 RESTful API,提供了一种清晰一致的方式来理解其功能并有效地使用它们。 在医疗保健领域,FHIR 成为数据交换和互操作性的领先标准。为了增强FHIR的互操作能力, HL7正式记录了FHIR OpenAPI规范,使开发人员能够将FHIR资源和操作无缝集成到他们的软件解决方案中。 FHIR OpenAPI 规范的优点: 标准化 API 描述:OpenAPI 规范提供 FHIR 资源、操作和交互的全面且标准化的描述。开发人员可以轻松了解基于 FHIR 的 API 的结构和功能,从而更轻松地构建集成并与医疗保健系统交互。 促进互操作性:促进开发人员之间的协作,推动 FHIR 标准和最佳实践的采用。该规范提供了一种通用语言和框架,用于讨论基于 FHIR 的集成和实现,促进开发人员之间的协作。 增强的文档和测试:交互式文档和测试套件,以便更好地理解和验证。开发人员可以创建详细的API文档,使其他开发人员更容易理解和使用基于FHIR的API。基于规范的测试套件可以对API集成进行全面的测试和验证,确保医疗数据交换的可靠性和准确性。 改进的开发人员体验:自动生成客户端库和 SDK 以实现无缝集成。这简化了集成过程,并减少了将 FHIR 功能合并到应用程序中所需的时间和精力 FHIR、OpenAI 和 OpenAPI Chain 如何协同工作? FHIR - AI 和 OpenAPI Chain应用程序利用 LangChain 来加载和解析 OpenAPI 规范( OpenAPI Chain )。之后,根据这些规范,通过 OpenAI 给出的提示链旨在理解自然语言查询并将其转换为适当的 FHIR API 请求。用户可以用简单的语言提出问题,应用程序将与所选的 FHIR API 交互以检索相关信息。 例如,用户可能会问:“患者 John Doe (ID 111) 的最新血压读数是多少?”然后,应用程序会将此查询转换为 FHIR API 请求,获取所需的数据,并以易于理解的格式将其呈现给用户。 FHIR - AI 和 OpenAPI 链的优势 用户友好的交互:通过允许用户使用自然语言查询与 FHIR API 交互,该应用程序使非技术用户可以更轻松地访问和分析医疗保健数据。 提高效率:该应用程序简化了查询 FHIR API 的过程,减少了获取相关信息所需的时间和精力。此外,它还有可能减少从应用程序中查找任何特定信息的点击次数(花费的时间)。 可定制:FHIR 标准简化了从任何 FHIR 服务器检索一致数据的过程,从而可以轻松定制。它可以轻松配置为与任何 FHIR API 无缝集成,为不同的医疗保健数据需求提供灵活且适应性强的解决方案。 FHIR 入门 - AI 和 OpenAPI 链 要开始使用 FHIR - AI 和 OpenAPI Chain 应用程序,请按照以下步骤操作: 从OpenAI Platform获取 OpenAI API 密钥。 获取 FHIR 服务器 API 端点。您可以使用自己的示例 FHIR 服务器(需要未经身份验证的访问),也可以按照InterSystems IRIS FHIR 学习平台中给出的说明创建临时示例服务器。 在线试用该应用程序或使用提供的说明在本地进行设置。 通过集成人工智能和自然语言处理功能,FHIR - AI 和 OpenAPI Chain 应用程序提供了一种与 FHIR API 交互的更直观的方式,使所有技术背景的用户都更容易访问和分析医疗数据。 如果您发现我们的应用程序很有前途,请在大奖赛中投票! 如果您能想到使用此实现的任何潜在应用程序,请随时在讨论线程中分享它们。 @Ikram Shah 致敬原创作者~
文章
Lele Yang · 六月 8, 2023

没有虚拟 IP 地址的数据库镜像

++ 更新:2018 年 8 月 1 日 使用内置于 Caché 数据库镜像的 InterSystems 虚拟 IP (VIP) 地址有一定的局限性。特别是,它只能在镜像成员驻留在同一网络子网时使用。当使用多个数据中心时,由于增加了网络复杂性( 此处有更详细的讨论),网络子网通常不会“延伸”到物理数据中心之外。出于类似的原因,当数据库托管在云端时,虚拟 IP 通常无法使用。 负载均衡器(物理或虚拟)等网络流量管理设备可用于实现相同级别的透明度,为客户端应用程序或设备提供单一地址。网络流量管理器自动将客户端重定向到当前镜像主服务器的真实 IP 地址。自动化旨在满足灾难后 HA 故障转移和 DR 升级的需求。 网络流量管理器的集成 当今市场上有许多支持网络流量重定向的选项。这些中的每一个都支持类似甚至多种方法来根据应用程序要求控制网络流量。为了简化这些方法,我们考虑了三个类别:数据库服务器调用 API、网络设备轮询或两者的组合。 下一节将概述这些方法中的每一个,并就如何将这些方法与 InterSystems 产品集成提供指导。在所有情况下,仲裁器都用于在镜像成员无法直接通信时提供安全的故障转移决策。可以在此处找到有关仲裁器的详细信息。 出于本文的目的,示例图将描述 3 个镜像成员:主机、备份和 DR 异步。但是,我们知道您的配置可能比这更多或更少。 选项 1:网络设备轮询(推荐) 在这种方法中,网络负载均衡设备使用其内置的轮询机制与两个镜像成员通信以确定主镜像成员。 使用 2017.1 中可用的 CSP 网关的mirror_status.cxw页面的轮询方法可以用作 ELB 健康监视器中对添加到 ELB 服务器池的每个镜像成员的轮询方法。只有主镜像会响应“SUCCESS”,从而将网络流量仅定向到活动的主镜像成员。 此方法不需要向 ^ZMIRROR 添加任何逻辑。请注意,大多数负载均衡网络设备对运行状态检查的频率都有限制。通常,最高频率不少于 5 秒,这通常可以接受以支持大多数正常运行时间服务级别协议。 对以下资源的 HTTP 请求将测试本地缓存配置的镜像成员状态。 /csp/bin/mirror_status.cxw 对于所有其他情况,这些镜像状态请求的路径应该使用与请求真实 CSP 页面所用的相同的层次机制解析到适当的缓存服务器和名称空间。 示例:测试 /csp/user/ 路径中应用程序配置服务的镜像状态: /csp/user/mirror_status.cxw 注意:调用镜像状态检查不会消耗 CSP 许可证。 根据目标实例是否是活动主机,网关将返回以下 CSP 响应之一: ** 成功(是主镜像成员) =============================== HTTP/1.1 200 OK Content-Type: text/plain Connection: close Content-Length: 7 SUCCESS ** 失败(不是主镜像成员) =============================== HTTP/1.1 503 Service Unavailable Content-Type: text/plain Connection: close Content-Length: 6 FAILED ** 失败(Caché服务器不支持Mirror_Status.cxw请求) =============================== HTTP/1.1 500 Internal Server Error Content-Type: text/plain Connection: close Content-Length: 6 FAILED 考虑下图作为轮询的示例。 同步故障转移镜像成员之间自动发生故障转移: 下图演示了将 DR 异步镜像成员提升到负载均衡池中,这通常假设同一个负载均衡网络设备正在为所有镜像成员提供服务(地理分割方案将在本文后面介绍)。根据标准 DR 程序,灾难恢复成员的提升涉及人为决策,然后是数据库级别的简单管理操作。但是,一旦采取该操作,就不需要对网络设备执行任何管理操作:它会自动发现新的主要设备。 选项 2:数据库服务器调用 API 在这种方法中,使用了网络流量管理设备,它有一个用故障转移镜像成员和潜在的 DR 异步镜像成员定义的服务器池。 当镜像成员成为主镜像成员时,向网络设备发出 API 调用以调整优先级或权重,以立即指示网络设备将网络流量定向到新的主镜像成员。 相同的模型适用于在主镜像成员和备份镜像成员都不可用的情况下提升 DR 异步镜像成员。 此 API 在 ^ZMIRROR 代码中定义为过程调用的一部分: $$CheckBecomePrimaryOK^ZMIRROR() 在此过程调用中,插入可用于相应网络设备的任何 API 逻辑和方法,例如 REST API、命令行界面等。与虚拟 IP 一样,这是网络配置的突然更改,不涉及任何应用程序逻辑以通知连接到故障主镜像成员的现有客户端正在发生故障转移。根据故障的性质,这些连接可能由于应用程序超时或错误、新主实例强制旧主实例关闭或客户端使用的TCP 保持活动计时器过期造成的故障本身而关闭。 因此,用户可能必须重新连接并登录。您的应用程序的行为将决定此行为。 选项 3:地理分散部署 在具有多个数据中心和可能地理分散的部署(例如具有多个可用性区域和地理区域的云部署)的配置中,需要使用基于 DNS 的负载均衡和本地负载均衡在一个简单且易于支持的模型中考虑地理重定向实践。 通过这种组合模型,引入了与 DNS 服务配合使用的附加网络设备,如 Amazon Route 53、F5 Global Traffic Manager、Citrix NetScaler Global Server Load Balancing 或 Cisco Global Site Selector,在每个数据中心、可用性区域或云地理区域与网络负载均衡器相结合。 在此模型中,前面提到的轮询(推荐)或 API 方法在本地用于操作任何镜像成员(故障转移或 DR 异步)的位置。这用于向地理/全球网络设备报告它是否可以将流量定向到任一数据中心。同样在此配置中,本地网络流量管理设备将其自己的 VIP 提供给地理/全球网络设备。 在正常稳定状态下,活动主镜像成员向本地网络设备报告它是主镜像成员并提供“启动”状态。此“启动”状态被转发到地理/全球设备以调整和维护 DNS 记录,以将所有请求转发到此活动的主镜像成员。 在同一数据中心内的故障转移场景中(备份同步镜像成员成为主镜像成员),API 或轮询方法与本地负载均衡器一起使用,现在重定向到同一数据中心内的新主镜像成员。由于新的主镜像成员处于活动状态,因此本地负载均衡器仍以“启动”状态响应,因此未对地理/全局设备进行任何更改。 出于本示例的目的,API 方法在下图中用于本地集成到网络设备。 在使用 API 或轮询方法到不同数据中心(备用数据中心中的同步镜像或 DR 异步镜像成员)的故障转移场景中,新提升的主镜像成员开始向本地网络设备报告为主要成员。 在故障转移期间,曾经包含主镜像成员的数据中心现在不再从本地负载均衡器向地理/全球报告“Up”。地理/全球设备不会将流量定向到该本地设备。备用数据中心的本地设备将向地理/全球设备报告“Up”,并将调用 DNS 记录更新以现在定向到备用数据中心的本地负载均衡器提供的虚拟 IP。 选项 4:多层和地理分散的部署 为了使解决方案更进一步,引入了一个单独的 Web 服务器层,既可以作为私有 WAN 的内部,也可以通过 Internet 访问。此选项可能是大型企业应用程序的典型部署模型。 以下示例显示了使用多个网络设备安全隔离和支持 Web 和数据库层的示例配置。在此模型中,使用了两个地理位置分散的位置,其中一个位置被视为“主要”位置,另一个位置纯粹是数据库层的“灾难恢复”位置。数据库层灾难恢复位置将在主要位置因任何原因停止服务的情况下使用。此外,此示例中的 Web 层将显示为双活,这意味着用户将根据各种规则(例如最低延迟、最低连接数、IP 地址范围或您认为合适的其他路由规则)定向到任一位置。 如上例所示,如果在同一位置发生故障转移,则会发生自动故障转移,并且本地网络设备现在指向新的主机。用户仍然连接到任一位置的 Web 服务器, Web 服务器及其关联的 CSP 网关继续指向位置 A。 在下一个示例中,考虑在位置 A 发生的整个故障转移或中断,其中主要和备份故障转移镜像成员都无法使用。然后,DR 异步镜像成员将被手动提升为主要和备份故障转移镜像成员。在升级后,新指定的主镜像成员将允许位置 B 的负载均衡设备使用前面讨论的 API 方法(轮询方法也是一个选项)报告“Up”。由于本地负载均衡器现在报告“启动”,基于 DNS 的设备将识别这一点并将流量从位置 A 重定向到现在的位置 B 以用于数据库服务器服务。 结论 在没有虚拟 IP 的情况下设计镜像故障转移有许多可能的排列。这些选项可应用于最简单的高可用性场景或具有多层的多地理区域部署,包括故障转移和 DR 异步镜像成员,以获得高可用性和容灾解决方案,旨在为您的应用程序维持最高水平的运营弹性. 希望本文提供了一些关于成功部署具有故障转移的数据库镜像的可能的不同组合和用例的见解,这些组合和用例适合您的应用程序和可用性要求。
文章
姚 鑫 · 六月 14, 2023

第五十七章 镜像中断程序 - 在手动故障转移之前确定备份是否处于活动状态

# 第五十七章 镜像中断程序 - 在手动故障转移之前确定备份是否处于活动状态 ## 在手动故障转移之前确定备份是否处于活动状态 假设有两个名为 `IRIS A` 和`IRIS B` 的故障转移成员。如果 `^MIRROR` 例程确认备份 (`IRIS B`) 在与主 (`IRIS A`) 丢失联系时处于活动状态,因此具有最新的来自 `IRIS A` 的日志数据,可以使用单个过程手动进行故障转移。当连接因主要故障而丢失时,不会造成数据丢失的风险。但是,当发生多个故障时,活动备份可能没有来自主服务器的所有最新日志数据,因为主服务器在连接丢失后继续运行了一段时间。 使用以下过程确定备份是否处于活动状态: 1. 确认 `IRIS` 实例 `IRIS A` 上的 `ISCAgent` 实际上已关闭(并确保它们在整个手动故障转移过程中保持关闭状态)。 2. 在 `IRIS B` 上,在终端的 `%SYS` 命名空间中运行 `^MIRROR` 例程(请参阅使用 `^MIRROR` 例程)。 3. 在主菜单中选择镜像管理,显示如下子菜单: ```java 1) Add mirrored database(s) 2) Remove mirrored database(s) 3) Activate or Catchup mirrored database(s) 4) Change No Failover State 5) Try to make this the primary 6) Connect to Mirror 7) Stop mirroring on this member 8) Modify Database Size Field(s) 9) Force this node to become the primary 10) Promote Async DR member to Failover member 11) Demote Backup member to Async DR member 12) Mark an inactive database as caught up 13) Manage mirror dejournaling on async member (disabled) 14) Pause dejournaling for database(s) ``` 4. 选择 `Force this node to become the primary` 选项。如果在联系丢失时备份处于活动状态,则会显示如下消息: ```java This instance was an active backup member the last time it was connected so if the primary has not done any work since that time, this instance can take over without having to rebuild the mirror when the primary reconnects. If the primary has done any work beyond this point (file #98), C:\InterSystems\MyIRIS\mgr\journal\MIRROR-GFS-20180815.009 then the consequence of forcing this instance to become the primary is that some operations may be lost and the other mirror member may need to be rebuilt from a backup of this node before it can join as a backup node again. Do you want to continue? ``` 如果有权访问主要文件的日志文件,则可以在继续之前确认引用的文件是最新的。 如果在与主服务器失去联系时备份未处于活动状态,则会显示如下消息: ```java Warning, this action can result in forcing this node to become the primary when it does not have all of the journal data which has been generated in the mirror. The consequence of this is that some operations may be lost and the other mirror member may need to be rebuilt from a backup of this node before it can join as a backup node again. Do you want to continue? ``` ## 手动故障转移到活动备份 如果 `^MIRROR` 例程的 `Force this node to become the primary` 选项确认备份在失去与主节点的连接时处于活动状态,请完成手动故障转移过程,如下所示: 1. 在要继续吗?提示继续该过程。 `Force this node to become the primary` 选项等待 `60` 秒以使镜像成员成为主要节点。如果操作未在 `60` 秒内成功完成,`^MIRROR` 报告操作可能未成功并指示您检查消息日志以确定操作是失败还是仍在进行中。 2. 一旦 `^MIRROR` 例程确认备份已成为主要备份,请在可以这样做时重新启动 `IRIS A`。当 `IRIS` 实例重新启动时, `IRIS A` 作为备份加入镜像。 ## 备份不活动时手动故障转移 即使 `^MIRROR` 例程未确认备份 ( `IRIS B`) 在与主 ( `IRIS A`) 失去连接时处于活动状态,仍然可以使用以下过程继续手动故障转移过程,但是如果这样做,会有数据丢失的风险。如本程序所述,可以在手动故障转移之前将最新的镜像日志文件从 `IRIS A`(如果有权访问)复制到 `IRIS` B,从而最大限度地降低这种风险。 1. 如果有权访问主服务器的镜像日志文件,请将最新的文件复制到 `IRIS B`,从 `IRIS B` 上的最新日志文件开始,然后包括来自 `IRIS A` 的任何后续文件。例如,如果 `MIRROR-MIRRORA-20180220.001`是 `IRIS B` 上的最新文件,复制 `MIRROR-MIRRORA-20180220.001` 和 `IRIS A` 上的任何更新文件。检查文件的权限和所有权,并在必要时更改它们以匹配现有日志文件。 2. 如果接受数据丢失的风险,请在提示时输入 `y` 以确认要继续;备份成为主要的。 `Force this node to become the primary` 选项等待 `60` 秒以使镜像成员成为主要节点。如果操作未在 `60` 秒内成功完成,`^MIRROR` 报告操作可能未成功并指示您检查消息日志以确定操作是失败还是仍在进行中。 3. 一旦 `^MIRROR` 例程确认备份已成为主要备份,请在可以这样做时重新启动 `IRIS A`。 - 如果 `IRIS A` 在 `IRIS` 实例重新启动时加入镜像作为备份,则不需要进一步的步骤。任何在故障成员上但不在当前主成员上的日志数据都已被丢弃。 - 如果在 `IRIS` 实例重新启动时 `IRIS A` 无法加入镜像,如重建镜像成员中描述的引用不一致数据的消息日志消息所示 `IRIS A` 上的最新数据库更改晚于最新的日志数据当 `IRIS B` 被迫成为主服务器时,它会出现在 `IRIS B` 上。要解决此问题,请按照该部分中的描述重建 `IRIS A`。
文章
Michael Lei · 六月 18, 2023

医疗行业的未来--数据与人的融合

在数字化时代,数据的重要性无可置疑。数据作为新型生产要素,不仅在宏观政策层面得到党和政府的大力推动,也是医院高质量发展的关键和改变医疗行业的驱动力。随着医疗信息化的迅猛发展,我们正迈向一个数据随处可及、人人可用易用的医疗信息化时代。这一时代将数据与人的需求相结合,致力于让数据能“主动”找到需要他们的医护人员和患者,每一个行业从业者,都应致力于为医护人员和患者提供简单易用的软件解决方案,减少工作量,提高效率,推动医疗行业的进步。 数据与人的融合是实现医疗行业数字化转型的核心。当然,医疗数据的收集、存储和管理对于提供高质量的医疗服务至关重要。然而,仅仅有大量的数据并不足够,我们需要将数据与人的需求紧密结合起来。这意味着我们应该让更多的数据关联起来,并且能服务于更多的人群,让患者能够随时随地访问他们的电子病历,让医生和科研人员也能及时有效地获取病人在医院围墙内外进行治疗和健康管理的数据,并且以直观易懂的方式呈现给医护人员和患者,使他们能够快速、准确地获取所需的信息。数据的融合还包括将不同来源的数据整合起来,为医护人员提供全面、完整的视图,同时基于医疗诊断的规则,不管是通过CDSS的形式,还是通过ChatBot(聊天机器人),帮助他们做出更好的决策。 实现数据和人的融合要按照人的需求投放数据。数字化转型的重要目标是为医护人员和患者提供所需的数据,以支持决策和治疗过程。这意味着我们应该了解用户的需求,将数据按照他们的角色、职责和关注点进行分类和投放。医生可能需要即时的患者数据、病历历史和最新的医学研究,而患者可能需要查看自己的健康记录、预约医生和接收个性化的健康建议。通过根据人的需求进行数据投放,新型软件可以提供个性化的服务和支持,形成千人千面,为每个用户提供有价值的信息。 简单易用是实现数字化转型成功的另一个关键。医护人员和患者使用的软件解决方案应该简单易用,不需要复杂的培训和技术知识。界面应该简单、直观、友好,操作流程简化和优化,以确保用户能够快速上手并高效地使用软件。简单易用的软件不仅能够减少用户的学习曲线和工作负担,还能提高用户满意度和工作效率。(比如Apple的医疗软件Apple Health,通过FHIR 技术,通过一个app能够连接数千家医院的病历数据,让患者可以通过一个app实现多家医院的互联网服务和数据整合) 无论是数字化转型还是高质量发展,软件为人服务始终是医疗信息化的核心宗旨。我们应该将软件看作是为人服务的工具,旨在帮助医护人员提供更好的医疗服务,提升患者的体验和健康结果。软件应该以用户体验为中心,并不断优化和改进,不断进行供给侧改革,以满足不断变化和不同人群的需求,而不是增加负担。 最后,数据会在安全可靠的前提下进行传递和流通。在互联网发展的早期时代,由于无法可依,野蛮生长,数据的滥用、隐私保护等存在很大问题。但随着《数据安全法》等法律法规的发布,相信未来的医疗行业数据一定会在更加安全、可靠、合规的前提下进行有序流动。 在未来的医疗信息化发展中,数据与人的关系将变得更加密不可分。通过数据的融合、按需投放、简单易用、安全可靠和以人为本的新一代软件,我们可以实现数据随处可及、人人可用易用的医疗信息化目标。这将为医护人员和患者提供更好的工作环境和医疗体验,推动整个医疗行业向前迈进。InterSystems公司作为创新性的数据平台解决方案供应商,我们始终致力于助力合作伙伴开发创新的解决方案,与合作伙伴一起共同实现这一愿景,改善医疗服务的质量和效率,提高患者体验的获得感的同时帮助医院降本增效,实现高质量发展。
文章
姚 鑫 · 六月 17, 2023

第六十章 镜像中断程序 - 使用主 ISCAgent 的日志数据进行 DR 提升和手动故障转移

# 第六十章 镜像中断程序 - 使用主 `ISCAgent` 的日志数据进行 `DR` 提升和手动故障转移 ## 使用主 `ISCAgent` 的日志数据进行 `DR` 提升和手动故障转移 如果 `IRIS A` 的主机系统正在运行,但 `IRIS` 实例没有且无法重新启动,您可以使用以下过程在通过升级后使用来自 `IRIS A` 的最新日志数据更新升级的 `IRIS C IRIS A` 的 `ISCAgent`。 1. 推广 `IRIS C`,选择 `IRIS A` 作为故障转移伙伴。 `IRIS C` 被提升为故障转移成员,从 `IRIS A` 的代理获取最新的日志数据,并成为主要成员。 2. 重新启动 `IRIS A` 上的 `IRIS` 实例,它作为备份重新加入镜像。 3. 在 `IRIS A` 重新加入镜像并变为活动状态后,可以使用使用升级的 DR 异步临时替换故障转移成员中描述的过程,将所有成员返回到它们以前的角色,首先是正常关闭 `IRIS C` ,然后在 `IRIS B` 的配置参数文件的 `[MirrorMember]` 部分中设置 `ValidatedMember=0`(请参阅配置参数文件参考中的 `[MirrorMember]`),将 `IRIS B` 重新启动为 `DR` 异步,将 `IRIS B` 提升为备份,并以 `DR` 异步方式重新启动 `IRIS C`。 注意:如果 `IRIS A` 的主机系统已关闭,但 `IRIS B` 的主机系统已启动,尽管其 `IRIS` 实例未运行,请按照手动故障转移到活动备份中所述在 `IRIS B` 上运行 `^MIRROR` 例程以确定 是否`IRIS B` 在发生故障时是一个活动备份。如果是这样,使用前面的过程,但在升级期间选择 `IRIS B` 作为故障转移伙伴,允许 `IRIS C` 从 `IRIS B` 的 `ISCAgent` 获取最新的日志数据。 ## 使用来自日志文件的日志数据进行 DR 提升和手动故障转移 如果 `IRIS A` 和 `IRIS B` 的主机系统都已关闭,但可以访问 `IRIS A` 的日志文件,或者 `IRIS B` 的日志文件和消息日志可用,您可以使用最新的日志数据更新 `IRIS C`从升级前的初级开始,使用以下过程。 1. 使用 `IRIS A` 或 `IRIS B` 的最新日志文件更新 `IRIS C`,如下所示: - 如果 `IRIS A` 的日志文件可用,则将最新的镜像日志文件从 `IRIS A` 复制到 `IRIS C`,从 `IRIS C` 上的最新日志文件开始,并包括来自 `IRIS A` 的任何后续文件。例如,如果 `MIRROR -MIRRORA-20180220.001` 是 `IRIS C` 上的最新文件,复制 `MIRROR-MIRRORA-20180220.001` 和 `IRIS A` 上的任何更新文件。 - 如果 `IRIS A` 的日志文件不可用但 `IRIS B` 的日志文件和消息日志可用: 1. 确认`IRIS B`很可能已被捕获,如下所示: a. 确认当`A`及其代理不可用时,`B`同时断开与 A的连接。可以通过在`Messages.log`文件中搜索类似于以下内容的消息来检查 `IRIS B`断开连接的时间: ```java MirrorClient: Primary AckDaemon failed to answer status request ``` b. 通过在其 `messages.log` 文件中搜索类似于以下内容的消息,确认 IRIS B 在断开连接时是活动备份: ```java Failed to contact agent on former primary, can't take over ``` 注意:`messages.log` 文件中的如下消息表明 `IRIS B` 在断开连接时未处于活动状态: ```java nonactive Backup is down ``` 当无法确认它是否已被追上时强制提升的 `DR` 异步成为主数据库可能会导致它成为主数据库而没有镜像生成的所有日志数据。因此,一些全局更新操作可能会丢失,而其他镜像成员可能需要从备份中重建。 2. 如果可以确认 `IRIS B` 处于活动状态,请将最新的镜像日志文件从 `IRIS B` 复制到 `IRIS C`,从 `IRIS C` 上的最新日志文件开始,然后包括来自 `IRIS B` 的所有后续文件。例如,如果 `MIRROR-MIRRORA-20180220.001` 是 `InterSystems IRIS C` 上的最新文件,请从 `IRIS C` 复制 `MIRROR-MIRRORA-20180220.001` 和任何更新的文件。检查文件的权限和所有权,并在必要时更改它们以匹配现有日志文件。 2. 在不选择故障转移合作伙伴的情况下将 `IRIS C` 提升为故障转移成员。 `IRIS C` 成为主要的。 3. 当 `IRIS A` 和 `IRIS B` 的问题得到修复时,尽早并在重新启动 `IRIS` 之前,在每个成员上的 `IRIS` 实例的配置参数文件的 `[MirrorMember]` 部分中设置 `ValidatedMember = 0`(参见 `[ MirrorMember]` 在配置参数文件参考)。说明指出,此更改是必需的。完成此操作后,在每个成员上重新启动 `IRIS`,从 `IRIS A`(最近成为主成员的成员)开始。 1. 如果成员在 `IRIS` 重新启动时作为备份或 `DR` 异步加入镜像,则不需要进一步的步骤。任何在故障成员上但不在当前主成员上的日志数据都已被丢弃。 2. 如果在 `IRIS` 实例重新启动时成员无法加入镜像,如重建镜像成员中描述的引用不一致数据的消息日志消息所示,则成员上的最新数据库更改晚于存在于上的最新日志数据 `IRIS C` 成为主要时。要解决此问题,请按照该部分中的描述重建成员。 4. 在大多数情况下,`DR` 异步系统不是主要故障转移成员的合适永久主机。在 `IRIS A` 和 `IRIS B` 重新加入镜像后,使用使用升级的 `DR` 异步临时替换故障转移成员中描述的过程将所有成员返回到它们以前的角色。如果 `IRIS A` 或 `IRIS B` 作为备份重新启动,则在备份处于活动状态时从正常关闭 `IRIS C` 开始,以故障转移到备份;如果 `IRIS A` 或 `IRIS B` 都重新启动为 `DR` 异步,将其中一个提升为备份,然后在 `IRIS C` 上执行正常关闭。将另一个以前的故障转移成员提升为备份,然后将 `IRIS C` 作为 `DR` 异步重启。
文章
Michael Lei · 二月 14

FHIR 用例集: 打破数字医疗壁垒,实现高质量发展

FHIR 用例集: 打破数字医疗壁垒,实现高质量发展 --促进互联互通,改进工作流程,提高数据洞察 简介 HL7® FHIR®(快速医疗互操作性资源)是以电子方式访问、交换和管理医疗信息的国际标准。与以往的标准不同,FHIR 可让帮助行业从业者轻松构建创新应用程序,有效地收集、汇总和分析来自不同来源的各种医疗保健和管理数据。医疗机构、社保/保险公司、政府机构、生命科学公司、医疗设备制造商和医疗科技等多种主体利用 FHIR 来简化信息流、提高数据洞察力、改善临床效果和业务成果。 FHIR 基于 JSON、HTTP 和 REST 等流行的网络技术。有了 FHIR,没有医疗信息化背景的软件开发人员也能使用熟悉的开发工具和开源技术,快速、轻松地满足政府机构、临床医生、研究人员、医疗行业从业者以及各类市场主体的数据需求。 FHIR 是一种灵活、适应性强的医疗数据模型,可轻松定制,以实现各种用例的互操作性。FHIR 由称为 "资源 "的离散、可计算的数据对象组成,以实现最佳效率。通过 FHIR 资源,应用程序可以访问单个医疗记录元素,而无需检索摘要文档中包含的所有数据。 本文回顾了 FHIR 的实际应用,并提供了 InterSystems 客户如何使用 FHIR 连接不同系统、加速数字化转型和提高数据洞察力的真实案例。 FHIR 商机无限 FHIR 正在改变医疗健康数据的访问和交换。无论您是为政府、医疗机构、公共卫生机构、保险公司还是厂商工作,FHIR 都能帮助您高效地获取、检索和共享来自电子病历系统、智能医疗设备、可穿戴设备、临床试验和公共卫生监测系统等不同来源的医疗数据。 当前应用和未来的 FHIR 用例FHIR支持实现大量的不同业务场景。您可以在各种部署场景中将 FHIR 用于各种目的。下面的列表总结了 FHIR 在不同行业领域的一些当前应用和潜在的未来用例。 医疗机构 应用场景: 患者数据访问 API机会:可以基于FHIR资源和技术框架实现卫健委互联互通三年攻坚计划以及国家数据局"数据要素x医疗行业"三年行动计划中提到的相关电子健康档案共享、检验检查互认、医疗行业数据要素流通、交易等战略目标,通过基于标准的 (FHIR) API 让患者以程序化的方式访问其健康数据(病史、化验结果、治疗计划等),以及未来可能的全国统一医疗健康档案超级APP(患者端)。 应用场景: 临床决策支持机会: 使用 FHIR 改善临床决策系统的洞察力。将实时电子病历数据安全传输到第三方系统进行分析并返回建议,帮助临床医生做出明智决策。与以往的标准和方法不同,使用 FHIR,您可以将临床决策支持功能直接嵌入电子病历,以简化流程。 应用场景: 医疗机构与支付方(医保/保险公司)的合规数据交换 机会: 利用 FHIR 自动化医疗机构与支付方之间的数据交换。消除资源密集、耗时的人工流程(降低飞行检查和审计成本)。允许医疗机构直接将电子病历数据转发给支付方,无需人工干预。 使用案例: 临床试验和研究机会: 使用 FHIR 无缝共享临床试验招募和分析所需的患者数据,加快临床研究进程。 设备制造商、医疗科技公司和应用开发商 用例:远程医疗和远程监控机会: 使用 FHIR 可将患者数据从家用医疗设备安全地传输给医疗服务提供者,以便他们有效地远程监控和管理患者。 用例: 移动医疗应用程序机遇: 患者可以在手机端访问在不同医院治疗的电子病历,并且确保患者数据的隐私和安全。 用例: 慢性病管理应用程序机会: 使用 FHIR 在医疗服务提供者之间无缝共享患者数据,以实现一致的监控和协调的护理计划。 用例: 药物管理应用程序机会: 为临床医生和护理人员创建多功能药物管理应用程序。使用 FHIR 在区域全民健康信息平台之间高效共享处方信息、用药计划和药房记录。 生命科学公司、政府机构和付款人 用例:健康信息交换机会: 使用 FHIR,政府、公共卫生、保险公司等可高效开展电子健康档案/电子病历共享调阅数据,以进行质量评估、护理差距识别、理赔裁定以及开展潜在的数据交易等。 用例: 护理计划机会: 利用 FHIR,让跨机构护理团队--医生、家庭医疗工作者、社区护理人员、家庭成员等--能够无缝交换信息。让不同的医疗保健系统进行有效沟通。确保所有护理团队成员都能获得最新的患者信息。 用例: 公共卫生报告机会: 使用 FHIR 有效地汇总和共享患者数据,以进行监控和人口健康管理,从而简化公共卫生报告。利用电子病历批量检索功能。(注:该功能自 2022 年起已成为所有美国电子病历系统的强制性要求,在WHO、OECD、欧盟、亚洲、港澳台等地区也正在逐步推广普及) 以上只是部分FHIR的用例,有了FHIR,从业者可以打开无限想象空间,创建丰富多样、互联互通的数字医疗创新应用。
文章
Hao Ma · 五月 24, 2023

Caché Mirroring 101:简要指南和常见问题解答

镜像101 Caché 镜像是一种可靠、廉价且易于实施的高可用性和灾难恢复解决方案,适用于基于 Caché 和 Ensemble 的应用程序。镜像在广泛的计划内和计划外中断情况下提供自动故障转移,应用程序恢复时间通常限制在几秒钟内。逻辑数据复制消除了存储作为单点故障和数据损坏的根源。升级可以在很少或没有停机时间的情况下执行。 但是,部署 Caché 镜像确实需要大量规划,并且涉及许多不同的过程。与任何其他关键基础设施组件一样,操作镜像需要持续监控和维护。 您可以通过两种方式使用本文:作为常见问题列表,或作为理解和评估镜像、规划镜像、配置镜像和操作镜像的简要顺序指南。每个答案都包含指向每个主题的详细讨论以及每个任务的分步过程的链接。 当您准备好开始规划镜像部署时,您的起点应该始终是Caché 高可用性指南“镜像”一章的镜像架构和规划部分。 经常问的问题 了解和评估镜像 镜像有什么好处? 镜像能否部署在虚拟化环境中? 镜像可以部署在云端吗? 镜像的基本设计是什么? 数据库副本如何与实时生产数据库同步? 自动故障转移是如何触发的?有没有它没有涵盖的情况? 镜像是否提供灾难恢复? 规划镜像 如何规划镜像的架构?将包括哪些成员,他们将在哪里? 哪些网络和延迟注意事项申请?镜像需要什么样的网络配置? 在故障转移时将应用程序连接重定向到新主节点的选项有哪些? 镜像中的 Caché 实例有哪些兼容性要求? 如何将现有数据库迁移到镜像? 如果将镜像部署在虚拟化环境中,我应该考虑什么? 配置镜像 我需要考虑哪些配置准则? 如何保护镜像? 如何配置镜像虚拟IP地址(镜像VIP)? 我在哪里以及如何安装仲裁器? 如何安装和启动 ISCAgent? 如何创建和配置镜像? 如何创建镜像数据库?如何将现有数据库添加到镜像? 如何确保 ECP 在故障转移后重定向应用程序服务器连接? 当镜像 VIP 不可用时(例如在云中),我如何确保重定向应用程序连接? 如何将 Caché Shadow转换为镜像? 我应该查看哪些其他配置细节? 管理镜像 如何监控镜像的运行? 如何修改镜像?我能做什么调整? 我可以在镜像中添加成员吗?消除一?如何完全删除镜像? 如果我需要暂时从镜像中删除成员怎么办? 我必须一次升级镜像吗?我必须把镜子从生产中取出来做吗? 我应该了解哪些其他镜像或镜像相关的管理程序和细节? 镜像中断程序 了解和评估镜像 镜像有什么好处? 对于基于 Caché 和 Ensemble 的应用程序,存在三种实现高可用性的主要方法: 故障转移集群、 虚拟化 HA和 Caché 镜像。前两者最大的缺点是依赖共享存储,存储失败后果不堪设想;可选的存储级冗余可以改善这一点,但也可以延续某些类型的数据损坏。此外,软件升级需要大量的停机时间,对于许多故障,应用程序恢复时间可能有几分钟。 通过使用两个具有独立存储和逻辑数据复制的物理独立系统,镜像避免了共享存储问题,升级不需要停机或停机时间很短,应用程序恢复时间通常为几秒钟。这种方案还提供可靠和强大的灾难恢复能力,灾难恢复站点(DR)可以位于距生产数据中心任何适当的距离。 镜像的主要限制是它只复制数据库本身;应用程序所需的外部文件需要额外的解决方案,安全和配置管理目前是分散的。 以下资源提供了这些 HA 方法的详细分析和比较,以及有关镜像优势的更多信息: 系统故障转移策略( Caché 高可用性指南) 高可用性策略(白皮书) 业务连续性的高可用性(视频) 缓存镜像:高可用性的冒险(视频) 镜像:吞吐量架构(在线学习) InterSystems Caché:数据库镜像:执行概述(白皮书) 镜像介绍(在线学习) HealthShare:通过镜像实现高可用性(在线学习) 镜像能否部署在虚拟化环境中? 镜像经常部署在虚拟化环境中。镜像通过自动故障转移对计划内或计划外中断提供即时响应,而虚拟化 HA 软件会在机器或操作系统意外中断后自动重启托管镜像成员的虚拟机。从而允许故障成员快速重新加入镜像以充当备份(或在必要时接管为主)。 有关使用此方法的信息,请参阅 InterSystems 白皮书高可用性策略。 镜像可以部署在云端吗? 镜像可以有效部署在云端。由于云网络限制,使用虚拟 IP 地址(镜像 VIP)在故障转移后重定向应用程序连接通常是不可能的,但这可以使用负载均衡器等网络流量管理器有效克服。 镜像的基本设计是什么? 一个 Caché 镜像通常包括物理上独立的主机上的两个 Caché 实例,称为故障转移成员;镜像自动将主角色分配给一个,而另一个成为备份。应用程序更新主数据库,而镜像使备份数据库与主数据库保持同步。 当主服务器发生故障或不可用时,备份服务器会自动接管主服务器,并将应用程序连接重定向到它。当主实例恢复运行时,它会自动成为备份实例。 操作员启动的人工切换可用于在计划的维护或升级停机期间保持可用性。 镜像可选地包含称为asyncs的其他成员,用于灾难恢复以及商业智能和数据仓库目的。 一个镜像也可以只使用一个故障转移成员和一定数量的异步,例如当灾难恢复是主要目标时。 数据库副本如何与实时生产数据库同步? 镜像的备份成员和异步成员使用日志文件(Journal文件)与主成员保持同步,日志文件包含自上次备份以来对 Caché 实例中的数据库所做更改的时间顺序记录。在镜像中,来自主数据库的日志文件被发送到其他成员并dejournaled日志记录——也就是说,其中记录的更改被应用到数据库的本地副本,使它们与主数据库保持同步。 日志记录从主数据库到备份的传输是同步的,主数据库在关键点等待备份的确认。这使故障转移成员保持紧密同步,并且备份处于活动状态(Active),并准备好接管为主。异步从主服务器异步接收日志数据,因此有时可能会滞后一些日志记录。 自动故障转移是如何触发的?有没有它没有涵盖的情况? 只有在确认主服务器在没有人工干预的情况下不能再作为主服务器运行时,备份服务器才能自动接管。当故障转移成员之间的直接通信中断时,备份从第三方系统( 仲裁器)获得帮助以确认这一点,仲裁器与两个故障转移成员保持独立联系。 此外,如果备份无法确认其拥有或无法从主服务器获取最新的日志数据,则无法发生自动故障转移。在每个故障转移主机上独立于 Caché 实例运行的代理进程,称为ISCAgents ,参与自动故障转移逻辑和机制的这一方面和其他方面。 假设仲裁器正常运行,几乎所有计划外的主机故障都包括在内;只有将故障转移成员彼此隔离并与仲裁器隔离的网络故障,才能阻止活动备份接管发生故障或不可用的主要成员。 镜像是否提供灾难恢复? 一种类型的异步镜像成员是灾难恢复 (DR) 异步。 DR 异步具有主数据库上所有镜像数据库的副本,并且可以随时提升为故障转移成员。当中断导致镜像没有正常运行的故障转移成员时,您可以手动切换到被提升后的 DR 异步;数据丢失的程度将取决于发生中断时 DR 异步落后于主服务器多远,以及前主服务器的主机系统是否正常运行,是否允许它获取额外的日志数据。提升的 DR 异步也可用于许多其他计划内和计划外中断情况。 规划镜像 如何规划镜像的架构?将包括哪些成员,他们将在哪里? 镜像的大小、成员资格和物理分布将取决于您部署它的原因以及许多基础设施和操作因素,允许多种可能的配置 具有两个故障转移成员的镜像通过自动故障转移提供高可用性。在可选的异步成员中,一个或多个 DR 异步可以提供数据安全和灾难恢复能力,而报告异步用于数据挖掘和商业智能等目的。单个报告异步最多可以属于 10 个独立的镜像,从而使其可以充当企业范围的数据仓库,将来自不同位置的相关数据库集合在一起。 如果不需要自动故障转移,镜像也可以包含一个故障转移成员和多个用于灾难恢复和报告目的的异步。 一个镜像最多可以包含 16 个成员。因为故障转移成员之间需要低延迟连接,因此通常位于同一地点,但异步成员可以位于本地或单独的数据中心,包括为 DR 异步上的数据提供最大安全性的地理位置偏远的位置。 一台主机上可以安装多个镜像成员,但需要额外规划。 哪些网络和延迟注意事项适用?镜像需要什么样的网络配置? 主要的网络配置考虑因素包括可靠性、带宽和网络延迟,这是应用程序性能的重要考虑因素。选择对主要成员传输给其他成员的日志数据进行压缩是通常但不必须的做法。 每个镜像成员都有几个不同的网络地址,用于不同的目的,在规划支持您的镜像所需的网络配置之前,应该很好地理解这些地址。 包含在单个数据中心、机房或校园内的镜像以及涉及双数据中心和地理上分离的灾难恢复的镜像的示例镜像和网络配置将帮助您定义所需的网络配置。 在故障转移时将应用程序连接重定向到新主节点的选项有哪些? 镜像和 Caché 内置了几个自动重定向选项,包括使用虚拟 IP 地址 (VIP) 进行镜像、将 ECP 数据服务器标识为镜像连接,以及镜像感知 CSP 网关。 镜像 VIP 通常是一种非常有效的解决方案,但确实需要一些提前规划,尤其是在网络配置方面。 还提供一系列外部技术选项,包括使用网络流量管理器(例如负载平衡器) 、自动或手动 DNS 更新、应用程序级编程和用户级程序。 镜像中的 Caché 实例有哪些兼容性要求? 在确定要添加到镜像的系统之前,请务必查看Caché 实例和平台字节顺序兼容性的要求。由于故障转移成员可以随时交换主要和备份的角色,因此它们应该尽可能相似; CPU 和内存配置应该相同或接近,存储子系统应该具有可比性。 如何将现有数据库迁移到镜像? 任何 Caché 数据库都可以轻松添加到镜像中;它所需要的只是能够备份和恢复数据库,或复制其CACHE.DAT文件。程序在下一节中说明。 如果将镜像部署在虚拟化环境中,我应该考虑什么? 在虚拟化环境中使用镜像时,规划虚拟镜像成员主机与物理主机和存储之间的正确关系很重要;镜像和虚拟化平台方面也有重要的操作考虑因素。 配置镜像 我需要考虑哪些配置指南? 如果您计划配置镜像虚拟 IP 地址 (VIP) ,InterSystems 建议将故障转移成员配置为使用相同的超级服务器端口和Web 服务器端口。 主要故障转移成员上的 Caché 实例配置(例如用户、角色、名称空间和映射)或未镜像的数据(例如与 SQL 网关和 Web 服务器配置相关的文件)都不会被其他镜像成员上的镜像复制。因此,在发生故障转移时启用备份或任何 DR 异步成员(可能被提升)以接管主服务器所需的任何设置或文件必须在这些成员上手动复制并根据需要进行更新。 不要在配置为镜像成员的任何系统上禁用 Internet 控制消息协议 (ICMP);镜像依靠 ICMP 来检测成员是否可达。 由于日志记录是镜像同步的基础,因此必须监视和优化故障转移成员上的日志记录性能并通常遵循日志记录最佳实践。特别是,InterSystems 建议您增加所有镜像成员上的共享内存堆大小(Shared memory heap size)。 如何保护镜像? 保护镜像通信的主要方法是 SSL/TLS,它使用 X.509 证书加密镜像内的所有流量。强烈建议使用 SSL/TLS 安全性。要在镜像上启用 SSL/TLS,您必须首先在每个镜像成员上创建一个镜像 SSL/TLS 配置;您可能会发现在创建镜像之前执行此操作最方便。启用 SSL/TLS 时,添加到镜像的每个成员都必须在主服务器上获得授权;成员的 X.509 证书更新时也是如此。 对于使用 SSL/TLS 的镜像的另一层保护,您可以激活日志加密。这意味着日志记录在主服务器上创建时使用其活动加密密钥之一进行加密,并在其他成员取消日志记录之前解密。备份和所有异步必须激活相同的密钥,备份和 DR 异步也必须使用它来加密数据。 配置镜像使用的网络的方式对镜像的安全性也有重要影响。 如何配置镜像虚拟IP地址(镜像VIP)? 镜像 VIP 是通过在创建和添加成员到镜像或修改镜像时指定详细信息来配置的,但是需要一些准备工作,包括所需信息的标识以及镜像成员的主机和 Caché 实例的可能配置。 我在哪里以及如何安装仲裁器? 仲裁器的位置应尽量减少仲裁器和故障转移成员意外同时中断的风险(如果两个故障转移都失败,则仲裁器变得无关紧要),因此其位置主要取决于故障转移成员的位置。单个系统可以配置为多个镜像的仲裁器,前提是它的位置适合每个镜像。托管镜像的一个或多个故障转移或 DR 异步成员的系统不应配置为该镜像的仲裁者。 任何运行 2015.1 或更高版本 ISCAgent 的系统,包括托管一个或多个 Caché 2015.1 或更高版本实例的系统,都可以配置为仲裁器。您可以准备任何其他受支持的系统(OpenVMS 系统除外),包括托管 2015.1 之前的 Caché 实例的系统,通过安装 ISCAgent将其配置为仲裁器。 如何安装和启动 ISCAgent? ISCAgent 随 Caché 自动安装,因此安装在任何镜像成员上。但是,必须将代理配置为在每个镜像成员上的系统启动时启动。 如何创建和配置镜像? 配置镜像是一个多步骤的过程: 创建镜像并配置第一个故障转移成员 配置第二个故障转移成员(如果需要) 授权第二个故障转移成员,如果使用 SSL/TLS(推荐) 配置异步镜像成员(如果需要,DR 或报告) 授权新的异步成员,如果使用 SSL/TLS(推荐) 在完成这些步骤中的任何一个之后,您可以在镜像监视器中查看镜像的状态以确认结果是否符合预期。 如何创建镜像数据库?如何将现有数据库添加到镜像? 在将数据库添加到镜像之前,您可能需要查看某些镜像数据库注意事项,这些注意事项与哪些内容可以镜像和哪些内容不能镜像、镜像和Shadow的同时使用、镜像数据库属性的传播以及镜像下每个实例的最大数据库数有关。 创建镜像数据库和添加现有数据库的过程是不同的,因为对镜像数据库的更改记录在镜像日志文件中,这与非镜像日志文件不同。如果数据库创建为镜像数据库,它从一开始就使用镜像日志文件,这使得通过在每个镜像成员上创建具有相同镜像名称的镜像数据库,可以很容易地将新数据库添加到镜像中。 当您将现有的非镜像数据库添加为主数据库上的镜像数据库时,它会从使用非镜像日志文件切换到镜像日志文件。因此,您不能简单地在其他成员上创建数据库,因为镜像无法将非镜像日志文件传送给其他成员。取而代之的是,在将数据库添加到主数据库的镜像后,您必须将其备份并在其他成员上恢复,或者将其CACHE.DAT文件复制到其他成员。 如何确保 ECP 在故障转移后重定向应用程序服务器连接? 无论您是否配置了镜像 VIP,您都可以通过将镜像 ECP 数据服务器配置为连接到它的每个 ECP 应用程序服务器上的镜像连接来确保 ECP 连接被重定向到新的主服务器。 (应用服务器不使用 VIP;因为它定期从指定主机收集信息,它会自动检测故障转移并切换到新的主服务器。) 当无法使用镜像 VIP 时(例如在云中),如何重定向应用程序连接? 只有当镜像成员位于同一网络子网上时才能使用镜像 VIP,而当它们位于不同的数据中心时通常不会出现这种情况。出于类似的原因,VIP 通常不是云中部署的选项。 可以使用一系列外部技术替代方案,包括使用负载均衡器(物理或虚拟)等网络流量管理器,可用于实现与 VIP 相同级别的透明度,向客户端应用程序提供单个地址或设备。其他可能的机制包括自动或手动 DNS 更新、应用程序级编程和用户级程序。 如何将 Caché Shadow转换为镜像? 镜像提供了一个Shadow到镜像实用程序,允许您将Shadow源和目标以及它们之间映射的Shadow数据库转换为具有主数据库、备份或异步数据库和镜像数据库的镜像。 我应该查看哪些其他配置细节? 虽然默认值通常是所需的全部,但您可能希望自定义 ISCAgent 端口号。 在主要故障转移成员上,您可能希望将代码从现有的^ZSTU或^ZSTART例程移动到用户定义的^ZMIRROR 例程,它允许您为特定镜像事件实现自定义的、特定于配置的逻辑和机制,以便它是直到镜像初始化后才执行。 将镜像与 Ensemble 一起使用时,您应该了解具有镜像数据的 Ensemble 命名空间的特殊要求以及 Ensemble Autostart 在镜像环境中的功能。 管理镜像 如何监控镜像的运行? 您可以在任何镜像成员的 Caché 管理门户中加载的Mirror Monitor提供有关的详细信息 镜像及其每个成员的运行状态,包括使用 SSL/TLS 时成员的 x.509 DN。 在故障转移成员上,两个故障转移成员的网络地址和仲裁器连接状态,以及仲裁器的地址;在异步上,报告异步所属的镜像。 在备份和异步成员上, 日志数据从主数据传输的状态和日志数据的Dejournaling,以及日志数据从主数据到达的速率。 加载镜像监视器的成员上镜像数据库的状态。 Mirror Monitor 还允许您执行许多操作,包括查看和搜索成员的日志文件、 将 DR 异步提升为故障转移成员或将备份降级为 DR 异步,以及激活、赶上和删除镜像数据库。 您可以在镜像成员的%SYS命名空间中使用 Caché 系统状态例程 ( ^%SS ) 来监视其镜像通信进程。 如何修改镜像?我可以修改什么? 在主服务器上编辑镜像以更改镜像的配置(包括 SSL/TLS、镜像 VIP 等)并在网络配置更改时更新成员的网络地址。您还必须编辑主服务器上的镜像以授权其他成员上的 X.509 证书更新。 在异步上编辑镜像以更改异步类型,将报告异步添加到另一个镜像,并进行其他特定于异步的更改。 您可以使用Mirror Monitor从任何成员(且仅该成员)的镜像中删除镜像数据库,尽管其影响因所涉及的成员类型而异。 我可以在镜像中添加成员吗?删除一个?如何完全删除镜像? 您始终可以将异步成员添加到镜像中,最多可添加 16 个成员。如果你有一个故障转移成员和少于 15 个异步,你总是可以添加一个备份。您还可以通过将 DR 异步提升为故障转移成员来替换备份,这会自动将当前备份降级为 DR 异步。 您可以编辑任何成员的镜像以从镜像中删除该成员。要完全删除镜像,您必须按特定顺序删除成员并采取其他步骤。 如果我需要暂时从镜像中删除成员怎么办? 您可以使用镜像监视器通过断开成员与镜像的连接来无限期地停止备份或异步成员上的镜像,例如进行维护或(在异步情况下)减少网络负载。 在异步上,您还可以暂停镜像中所有数据库的Dejournaling,而不暂停从主数据库到异步数据库的日志数据传输。 我必须一次升级镜像吗?我必须把镜像从生产中取出来做吗? 镜像的所有故障转移和 DR 异步成员必须是相同的 Caché 版本,并且只能在镜像升级期间有所不同。一旦升级的成员成为主要成员,您就无法使用其他故障转移成员或任何 DR 异步成员,直到它们也升级为止。通常,最佳做法是同时将报告异步升级到同一版本。 您选择的升级过程取决于您是进行维护版本升级、 不对镜像数据库进行任何更改的主要升级,还是对镜像数据库进行更改的主要升级。所提供的程序旨在最大限度地减少应用程序停机时间;在前两种情况下,您通常可以完全避免停机时间,而在后一种情况下,它通常仅限于执行计划的故障转移和进行所需的镜像数据库更改所需的时间。 当您在计划停机期间进行重大升级并且不需要最小化应用程序停机时间时,您可能还想使用一个更简单的过程。 我应该了解哪些其他镜像或镜像相关的管理程序和细节? 您可以在未使用SSL/TLS 的镜像上启用安全性,只要每个成员都具有有效的镜像 SSL/TLS 配置。 您可以为未使用它的镜像激活日志加密,只要该镜像使用 SSL/TLS 安全性并且用于加密主要日志数据的活动加密密钥在备份和所有异步中也处于活动状态。 根据您的硬件和网络配置,您可能需要调整镜像的服务质量超时(QoS 超时)设置,这在故障转移机制中起着重要作用。通常,如果需要更快地响应中断,则可以在部署在具有专用本地网络的物理(非虚拟化)主机上的镜像上减小此设置。 如果绝大多数镜像数据库更新由高度压缩的数据(如压缩图像)或加密数据组成,则日志数据压缩预计不会有效,因此可能会浪费 CPU 时间。在这种情况下,您可以选择配置或修改镜像以将日志数据设置为Uncompressed 。 (使用 Caché 数据库加密或日志加密不是选择压缩的一个因素。) 如果主要成员和其他镜像成员之间的网络延迟成为问题,您可以通过微调操作系统 TCP 参数来减少它,以允许主要成员和备份/异步成员分别建立适当大小的发送和接收缓冲区. ^MIRROR 例程为所有镜像任务提供了管理门户的命令行替代方案。 SYS.Mirror API 提供了以编程方式调用通过管理门户和^MIRROR例程可用的镜像操作的方法。 镜像中断程序 有关处理各种计划内和计划外镜像中断情况的建议过程的概述,请参阅镜像中断过程。
文章
Qiao Peng · 十月 17, 2023

FHIR生态

2023年6月底,世卫组织(WHO)和HL7签署了合作协议,利用HL7 FHIR提供互操作性,来支撑WHO的SMART指南(SMART Guideline)愿景 - 使用数智化的方式推动并加速一致化的健康干预措施建议,让世界上每个人都能立即从临床、公卫和数据使用建议中充分受益。 作为WHO的《2020-2025 年全球数字卫生战略》的一部分,SMART 指南使用 FHIR 、HL7的临床质量语言 (CQL) 和ICD标准以表达 WHO 的各种健康和临床指南,实现数据互操作、决策支持与指标、术语的一致性。这些标准被进一步利用来为各国及其合作伙伴开发一个由软件库、服务和工具组成的支持生态系统,并作为数字公共产品服务全球卫生健康事业。 为什么世卫组织会采用FHIR作为卫生信息互操作的标准在全球推广其一致化的健康干预措施建议?因为FHIR不仅标准成熟适用,而且还具有一个极具生命力的生态。 一个有生命力的标准会吸引生态的构建,而完善的生态将促进标准的成熟和演进。HL7 FHIR作为新一代的卫生信息互操作标准,其生态已经初具规模并蓬勃发展。 HL7 FHIR的知识产权类型 HL7 FHIR的知识产权是CC0,也就是知识共享。任何机构、组织和个人都可以无需向HL7申请而免费使用、扩展FHIR的标准。其知识产权类型配合FHIR标准的丰满程度,极大地鼓励和促进了基于FHIR的生态建设,应该也是WHO采用FHIR的原因之一。 FHIR的标准发布和标准的推广 标准应该是方便可及的 - 不仅有用户可阅读、可理解的文字说明,更需要要可以直接下载让计算机可用、可理解的电子结构化标准。 HL7 FHIR官网详细说明了每个版本、每个FHIR资源的结构与关系、使用范围、用例和示例。在下载页面提供了各种版本的标准、值集、profile和工具的免费下载。 对于用户的扩展、再约束和实施指南,有专门的实施指南注册和发布网站。这里可以免费注册自己的实施指南、也可以访问、查阅和下载别人的实施指南,从而让基于FHIR标准的自定义扩展可以无障碍地被分享、使用、理解,甚至进一步扩展。 下图是发布在注册网站的按用例类型统计的FHIR实施指南: 这众多方向的实施指南也是FHIR横跨交叉领域建立起成熟生态的体现。FHIR有什么快速建立生态的秘诀? 成熟的卫生信息标准要能应对各种行业互操作挑战,FHIR有一个四层机制用于制定标准并用各种互操作挑战来测试、验证和推进FHIR落地: 工作组(workgroups):FHIR有40多个工作组,专注不同的领域的需求,并制定和改进相关FHIR资源和用例标准。例如FHIR基础架构、基因组学、电子健康档案、财务管理、设备... 加速器计划(accelerators):为了推进在主要互操作领域的成熟和落地,FHIR建立加速器计划让每个领域的各个利益相关方参与进来,通过研究各方的需求、凝聚各方的智慧来推动FHIR。如今已经有8个不同领域的加速器计划: 例如Vulcan是专注连接临床研究、转化研究和医疗保健的加速器,它的成员不仅有HL7这样的标准开发组织,还有学会 - 例如约翰霍普金斯医学院,行业协会 - 例如全球医疗数据科学社区PHUSE,政府机构 - 例如FDA,技术厂商 - 例如InterSystems,药厂 - 例如GSK,甚至意见领袖。 课题(projects):FHIR通过课题,研究具体的需求、实现具体的目标,让FHIR扎实、可用。例如Vulcan加速器有以下课题: 课题 目标 Schedule of Activities (SoA) 活动安排 用FHIR表示电子表格中的活动时间表。 使得研究中的每项活动的描述、时间和标识都能保持一致 Real World Data (RWD) 真实世界数据 以标准化的格式从EHR中提取数据,以支持临床研究,特别是向监管机构提交数据 Phenotypic Data 表型数据 为基因组研究和基因组医学提供更多高质量的标准化表型信息 Electronic Product Information (ePI) 电子产品信息 为产品信息(各论)定义一个共同的结构,支持患者对产品数据的跨边界交换 Adverse Events (AE) 不良事件 支持对不良事件的报告和格式进行标准化。 提高相关FHIR资源的成熟度 FHIR to OMOP FHIR与OMOP映射 支持开发FHIR到OMOP的数据传输,以便更好地分析临床数据,用于研究 连接测试马拉松(connectathons):这是一个针对技术厂商的FHIR互操作系列化的一致性认证。每年3次的连接测试马拉松会确定众多的具体互操作用例,厂商选择并参与这些用例,用FHIR进行跨厂商的互操作测试。它不仅是技术厂商验证自己的FHIR互操作一致性的试验场,更是通过测试和反馈来发现标准的问题、确定标准适用性的大型沟通会。 FHIR confluence上公布有历次的连接测试马拉松的用例说明、实施指南、学习资料等详尽的资料。 除了这些手段,HL7还有FHIR认证,建立FHIR标准的智力资源池、确保FHIR在全球的正确采纳。 FHIR标准的适应性 FHIR的适应性核心在于其标准的设计 - 通过profile,在资源模型层面已经考虑到如何让用户进行不破坏标准的扩展和再约束;在标准成熟上,设计了成熟度模型,让标准基于实际使用和反馈逐步成熟。 Profile可以让用户裁剪、扩展FHIR标准,以适用于自己的术语体系和用例场景,实现基于统一标准的千人千面。 在标准的理解与反馈上,FHIR官方沟通提供了开放的交流和反馈的渠道。 FHIR生态的工具 成熟的生态工具是FHIR的一大亮点。这些工具是整个生态贡献的,好的工具得到广泛认同和采纳,既促进了标准的理解与使用、也避免了低水平的重复建设。 1. 标准学习工具: 理解和学习是标准推行的第一要务。除了汗牛充栋的学习材料和视频,FHIR还有不错的学习网站,例如Clinfhir ,最初设计是方便医生理解如何用FHIR构建和解决自己的用例的,但实际上也被广大卫生信息从业者用于理解FHIR标准。 2. 测试数据生成工具: 想学习标准?没有什么比直观的数据更能说明问题了。FHIR生态下有名的Synthea是一个基于马塞诸塞州的患者真实数据经过统计、混淆后的FHIR测试数据生成工具,可以按用户要求生成指定数量的、符合真实数据分布的FHIR资源,会为每个生成的虚拟患者生成一个FHIR boundle文件,并生成对应的医院、医生等FHIR资源。大家可以免费下载Synthea使用它产生测试数据。 另外,国内也广泛使用的MIMIC - 麻省理工贝斯以色列迪康医学中心的有5万多患者真实完整的高质量重症医疗数据集,如今也有了FHIR版本。 3. FHIR服务器: 还没有FHIR服务器,怎么测试FHIR? FHIR生态下有大量的免费沙箱,用户可以选择它们进行标准的学习和测试。例如官网提供的沙箱和各个厂商提供的沙箱。通过各种API工具,例如postman,学习者无需注册即可以了解FHIR标准的方方面面,甚至将自己的测试数据加载进去并测试自己的解决方案。 4. 标准扩展和再约束构建工具: 如何方便、直观地构建自己的术语、扩展和再约束(Profile)和用例?FHIR生态下有众多公司提供的免费工具可用 - 随君取用。例如术语扩展可以用Snapper和FSH、进行小规模profile开发可以用可视化的Forge或Trifolia-on-FHIR、进行大规模的profile和实施指南开发可以用FSH。 5. 标准验证工具: 需要基于profile对FHIR资源进行校验?资源更多了,不仅有FHIR官网提供的FHIR资源校验网页,还有各种开发语言版本的校验工具代码: JAVA C#/DotNet FHIR生态下百花齐放的各种应用架构、应用方向 更令人眼前一亮的是FHIR生态下各种应用架构、应用方向和众多其它生态对FHIR的采纳。 应用开发架构: FHIR提供了标准卫生信息模型和相应的API,为行业应用的快速开发提供了坚实的基础。FHIR生态下最有名的SMART on FHIR,实现即插即用和可复用的应用开发架构。在国际卫生信息互操作标准发展简史中有简要介绍。 SMART on FHIR市场已经有大量的应用可以直接下载部署。 决策支持架构: 决策支持已经是卫生信息数字化转型的核心需求之一。卫生信息化已经建设了各种基于知识库和基于机器学习的决策支持系统,涵盖了临床、业务管理、费用、组学与科研、公卫、健康管理等全部业务,但仍面临众多挑战。 任何知识库系统和决策支持系统面临的一个关键挑战是决策支持的可移植性!如果决策支持厂商都按自己的数据、术语和服务标准构建解决方案,用户在使用多个决策支持产品时,将面临大量数据转换和映射及服务集成带来的非常高的实施成本和潜在决策错误风险。 FHIR通过Clinical Reasoning模块和CDS Hooks分别提供了本地决策支持架构和外部决策支持架构,通过标准化降低成本和风险、提高决策效率和范围。这里是对CDS Hooks的介绍。 其它标准对FHIR的采纳: 相较于之前流行的互操作标准,FHIR在标准化、灵活性、可用性 三方面取得了很好的平衡。FHIR资源模型比大多数的行业通用数据模型(CDM)都简化,方便使用。曾经各自为战的众多标准都发现FHIR无处不在,且FHIR资源和API可以作为自己的数据和访问数据的基石,而融入FHIR生态可以更方便获得数据、获得更多的推广、发挥更大的价值,因此一系列的XX on FHIR项目应运而生 - 或者直接采纳FHIR、或者与FHIR相兼容。除了上面提到的SMART on FHIR,这里简单汇总一下主要的已完成和进行中的on FHIR项目和标准。 1. IHE IHE(Integrating the Healthcare Enterprise)是国际上比较流行且成功的卫生信息交换服务规范。它一直采用流行和稳定的互操作基础标准来开发自己的服务规范,最初使用DICOM + HL7 V2消息,后来用到HL7 V3 和CDA。IHE发现新的FHIR互操作标准有助于应对新的用例、并更好解决老的用例,认为FHIR会成为最流行的互操作基础标准,因此已经发布了很多基于FHIR的IHE服务,尤其是那些和移动业务相关的服务,例如移动患者人口统计查询 (PDQm)。 2. OMOP on FHIR OMOP(Observational Medical Outcomes Partnership)是包括国内在内全球科研人员进行真实世界研究的重要工具,它开发了通用数据模型CDM和分析工具库。 HL7国际和OHDSI宣布合作提供单一的通用数据模型,用于共享临床护理和观察研究信息 - 这就是OMOP on FHIR项目。 OMOP-on-FHIR 是构建在 OMOP CDM 数据库之上的 FHIR 服务器,它提供中间映射层,实现OMOP CDM和FHIR资源之前的双向转换,从而打通两大生态,使临床医生和研究人员能够从多个来源提取数据并以相同的结构进行分析处理与共享交换而不会降低数据质量,可以同时使用两个生态下丰富的应用与工具,利用各自的生态优势。例如OMOP让FHIR生态可以利用其丰富的预测模型,而FHIR让OMOP的研究分析可以集成到临床工作流程中,推动精准医学的落地。 3. FHIR to CDISC Joint Mapping CDISC 是一个标准开发组织,开发了生物制药行业使用的诸多数据标准,常用于提交临床试验数据以进行分析和监管审批。 通过与HL7合作,FHIR to CDISC Joint Mapping实施指南定义了FHIR 与三个特定 CDISC 标准之间的映射: 研究数据列表模型实施指南 (SDTMIG) 3.2 临床数据采集标准协调实施指南 (CDASH) 2.1 实验室1.0.1 通过简化 HL7 FHIR和 CDISC 标准之间的数据转换,消除使用临床信息支持科研的障碍。用途包括: 捕获“真实世界证据”(RWE),让那些不是为临床试验目的采集的数据可以用于研究监管 利用FHIR 的 SMART等技术,直接在临床系统内部捕获试验驱动的数据,而不是建立单独的临床试验管理解决方案 在回顾性研究中更容易利用临床数据 创建病例报告表单 (CRF),链接到使用 FHIR 资源和Profile定义的数据元素 使两个标准社区的专家能够理解彼此的术语,并随着两套规范的不断发展更好地协调它们 4. 通用数据模型协调 Common Data Models Harmonization(CDMH) 在卫生信息领域,有众多的通用数据模型(Common Data Models)服务于不同的或相同的业务领域。虽然都是“通用”数据模型,但数据在彼此之间并不通用。 FHIR的细颗粒度统一语义资源模型可以作为众多通用数据模型间的桥梁。通用数据模型协调(CDMH)目标就是借助FHIR打通各个通用数据模型,让它们的数据可以相互转换。 CDMH 项目由美国FDA 领导,与其他联邦政府机构合作。已发布的通用数据模型协调 (CDMH) FHIR 实施指南 (IG) 将重点放在以患者为中心的结果研究 (PCOR) 和其它目的提取的观察数据的映射和转换为 FHIR 格式。该项目重点关注以下四种通用数据模型 (CDM) 到 FHIR 的映射: 以患者为中心的结果研究网络 (PCORNet) 整合生物学和床边 (Informatics for Integrating Biology & the Bedside - i2b2) 临床试验 (ACT) 信息学,也称为 i2b2/ACT。 观察性医疗结果合作伙伴 (OMOP) 美国食品和药物管理局的哨兵(Sentinel) 5. Arden Syntax on FHIR 和HL7的临床质量语言(Clinical Quality Language - CQL)类似,Arden Syntax 是一种结构化、可执行的医学知识表示和处理语言,将医学知识表达为独立的单元 - 医学逻辑模块(Medical Logical Modules),常用于设计CDS系统,构建临床指南规则和临床决策规则。 新版本 Arden Syntax 3.0 版采用FHIR进行扩展,重新定义了基于FHIR的标准化的数据模型和数据访问方式。作为经过审计、基于共识的迭代 HL7 标准开发流程的一部分,3.0版已成功通过投票。 6. HL7 V2 to FHIR HL7 V2在全球依然有很高的采纳度,但其局限性和FHIR的成熟度都在推动从V2到FHIR的迁移。HL7 V2 to FHIR 项目建立实施指南,将HL7 V2的组件映射到FHIR组件:V2的消息、消息段、数据类型和词汇分别映射到 FHIR 的Bundle、FHIR资源、数据类型和编码系统,并对FHIR进行相应扩展以弥补二者间的差距。 7. C-CDA on FHIR C-CDA是最广泛实施的 HL7 CDA 实施指南之一,涵盖了临床护理的文档范围。CDA 和 FHIR 之间的互操作能力是推动临床文档进化的重要渠道。 C-CDA on FHIR 实施指南 (IG) 定义了一系列 FHIR 配置文件,以表示 C-CDA 中的各种文档类型,并弥补二者设计上的差异。C-CDA on FHIR 利用FHIR使文档标准更为精简。 还有更多的on FHIR项目没有介绍到,例如SNOMED on FHIR、PDMP on FHIR... 同时可以预期还会有越来越多的on FHIR项目会不断涌现。 不仅是这些on FHIR 项目,越来越多的机构发现FHIR的价值,将自己原来的数据模型改为FHIR。例如美国互操作核心数据集USCDI(U.S. Core Data for Interoperability) 起初采用通用临床数据集CCDS作为模型, 如今已经完全采纳FHIR,并且成为美国国家FHIR标准US Core的一部分。FHIR也得到了很多国家采纳作为国家级卫生信息互操作的标准。 大规模数据统计与分析: 一个好的标准应该有助于解决完整的行业需求。FHIR作为行业互操作标准已经超越了传统互操作的能力范围,除了互操作的数据模型、消息、文档、服务和API,FHIR服务器加上FHIR资源仓库为大规模的卫生信息持久化和访问提供了方案。 FHIR的完整蓝图目前尚缺一块拼图 - 基于FHIR的大规模数据统计与分析。 1. 大规模数据检索 FHIR API提供检索类型的API,通过查询参数(Search Parameter)对资源进行检索。 例如: 想要获取所有检验项目为loinc 1234-1,且检验结果小于9.2的Observation资源,可以用这样的查询参数: GET http://fhirsvr.com/Observation? code-value-quantity=loinc|1234-1$lt9.2 除了FHIR Core发布的查询参数,用户还可以扩展自己的查询参数,满足检索需求。 FHIR标准里的FHIR Path为FHIR资源模型提供了类似于XPath的资源路径导航和获取语言,可以方便地筛选、过滤层次化的FHIR数据。 但FHIR查询API和FHIR Path都仅适合于单资源类型的检索,对于需要多类型资源联合分析、汇聚、统计等分析需求无能为力。 2. 大规模的数据统计分析 HL7为临床质量指标与决策支持提出了临床质量语言(Clinical Quality Language - CQL) ,CQL如今基于FHIR,使用FHIR资源模型来构建标准化的指标体系,以支持决策和基于指标的管理。 对于科研数据分析,借助上面介绍的OMOP on FHIR和其它项目,用户可以用自己熟悉的科研工具并利用FHIR数据支持自己的科研工作,本质上是将FHIR数据转换并导入自己的科研工具。 对于通用大规模数据统计分析,虽然FHIR提供了API、FHIR资源数据序列化的JSON、XML可以作为文档进行分析,但市面上的统计分析工具和机器学习工具大都支持SQL,SQL也是最流行的数据统计分析语言。 FHIR的深层次化模型是立体的、对象化的,而SQL是扁平的、表格化的。这个差异让FHIR对主流分析工具和机器学习工具不友好。这对基于FHIR原生的大规模数据分析利用造成了障碍,是FHIR最需要完善的那一块。 FHIR和生态已经创立了很多项目,努力补上这一环。 SQL on FHIR SQL on FHIR项目的思路是为SQL用户提供FHIR的SQL表示层。SQL表示层提供一个机制:让用户根据自己的需要基于FHIR Path定义视图。这里的视图不是SQL视图,而是一个SQL模型的逻辑表达,由一个新的FHIR工件ViewDefinition定义。各个技术厂商负责物理实现它并展现为SQL表。 例如下面的视图定义: { "resourceType": "http://hl7.org/fhir/uv/sql-on-fhir/StructureDefinition/ViewDefinition", "select": [ { "column": [ { "path": "getResourceKey()", "alias": "id" }, { "path": "gender" } ] }, { "column": [ { "path": "given.join(' ')", "alias": "given_name", "description": "A single given name field with all names joined together." }, { "path": "family", "alias": "family_name" } ], "forEach": "name.where(use = 'official').first()" } ], "name": "patient_demographics", "status": "draft", "resource": "Patient" } 它定义一张这样的SQL表: 考虑到FHIR资源模型的复杂,SQL on FHIR目前尚待成熟。当前是版本2,尚未发布,且有很多限制,例如不能在视图里定义跨资源的字段。 技术厂商的FHIR资源SQL实现 除了SQL on FHIR项目,很多技术厂商也在借助自身技术上的优势为FHIR提供SQL访问层。 例如InterSystems IRIS是一个多模型数据平台技术,它可以同时支持对FHIR资源逻辑模型使用对象建模、对FHIR序列化的JSON/XML使用文档建模,并将这些模型投射为SQL模型。InterSystems IRIS正是借助于这个特性,提供一个名为FHIR SQL构建器(FHIR SQL Builder)的工具,用户通过图形化方式拖拽建立需要的SQL模型,而无需拷贝和转换数据。 FHIR生态正展现出蓬勃的生命力,如今已经是百花齐放。FHIR展现的统一行业语义能力和强大的生态,不仅帮助WHO发布数字公共产品服务,也可以赋能卫生信息数字化转型。
文章
Michael Lei · 四月 9

Open AI 与 IRIS 集成 - 文件管理

人工智能不仅限于通过带有说明的文本生成图像,或通过简单的指示创建叙事。您还可以制作图片的变体,或为已有图片添加特殊背景。此外,您还可以获得音频转录,无论其语言和说话者的语速如何。让我们来分析一下文件管理是如何工作的。 问题描述 在分析 OpenAI 有关需要将文件作为输入值的方法的信息时,必须使用 multipart/form-data 提供参数。 在 IRIS 中,我们知道如何使用 JSON 内容创建对 POST 方法的调用。但在这种情况下,使用带有 Base64 格式文件内容的参数并不实用。 要在多址/表单数据(multipart/form-data)中包含文件内容,必须使用%Net.MIMEPart.类。 要在我们的调用中包含文件,应创建一个与类对象 %Net.MIMEPart 相关联的 Content-Disposition 标头 set content = ##class(%Net.MIMEPart).%New() set contentDisposition = "form-data; name="_$CHAR(34)_"image"_$CHAR(34) set contentDisposition = contentDisposition_"; filename="_$CHAR(34)_fileName_$CHAR(34) do content.SetHeader("Content-Disposition",contentDisposition) 由于我们使用请求类来保留进程的值,因此我们必须将 Base64 内容转换为流,以构成内容的主体。 我们可以使用StreamUtils实用程序将 Base64 转换为流。 注意:"pImage"变量包含文件内容的 Base64 字符串。 Do ##class(HS.Util.StreamUtils).Base64Encode(pImage, .tStream) Set content.Body = tStream 不过,在 2023 年全球峰会上,我有幸从 InterSystems 专家那里学到了一个更好的技巧。他告诉我,这种执行方法比 StreamUtils 更有效,因为 StreamUtils 最后会循环读取字符串并记录到 Stream 中。这个解决方案就像使用 JSON 并将其转换为 Stream 的 Get 一样简单。 set contentfile = {} set contentfile.file = pImage set content.Body = contentfile.%Get("file",,"stream<base64") 在调用中包含了所需的所有参数后,我们就可以创建一个新的 MIMEPart 类来封装部件了。 Set rootMIME = ##class(%Net.MIMEPart).%New() do rootMIME.Parts.Insert(content) set writer = ##class(%Net.MIMEWriter).%New() set tSC = writer.OutputToStream(tHttpRequest.EntityBody) set tSC = writer.WriteMIMEBody(rootMIME) Set tContentType = "multipart/form-data; boundary="_rootMIME.Boundary set tSC = ..Adapter.SendFormDataArray(.tHttpResponse, "POST", tHttpRequest,,,url) 这就是我们如何将文件内容发送到我们在 OpenAI 中需要的方法。 Image files图像文件 图像方法允许您发送图片并进行变化。由于所有插图都必须是 PNG 格式,因此当我们以 Base64 格式指明文件内容时,文件名会随机生成,并带有 PNG 扩展名。下面是一个如何更改照片的示例。 Original Variation 正如你所看到的,程序以自己的方式解释指令。它认为公司的标志是一个圆圈,所以用另一个圆圈代替了它。它还发现办公室有一扇玻璃门,于是用另一扇玻璃门代替,但暂时用砖墙代替。此外,它还修改了衬衫的颜色,并改变了男子手臂的位置。此外,OpenIA 还允许您通过提供一个蒙版来编辑图像,蒙版上有您想要插入提示内容的区域。利用同一幅图像,我应用了一个去掉图像背景的蒙版。 Original Mask 当我要求它把我传送到牙买加海滩时,得到了如下结果: 现在,下次见到亲朋好友时,您就可以炫耀自己的假期了 😊 Image图像 Endpoint: POST https://api.openai.com/v1/images/variations 它允许你对已有的图像进行修改。由于它不需要提示您要如何修改,因此我们必须相信人工智能的品味,它会如何解释这张图片。此外,我们还可以定义大小和返回结果的方式,无论是通过链接还是 Base64 格式的内容。 输入参数如下: image: 必选 在这里,您要提及要转换的图像文件。 n: 可选. 默认为 1 在此区域,您可以决定生成图像的最大数量。(使用 1 到 10 之间的数字)。 size: 可选. 默认 1024x1024 定义图像大小,其数值必需为 “256x256”, “512x512”, 或者 “1024x1024”. response_format: 可选.默认是“url” 这个参数是关于您希望如何返回生成图像的格式。此处的值应为 "url "或 "b64_json"。 Endpoint: POST https://api.openai.com/v1/images/edits 它可以让你修改现有的图片,根据掩码文件,按照提示创建图片。此外,我们还可以指定尺寸和返回结果的方式,无论是通过链接还是 Base64 格式的内容。输入参数如下: image: 必选 如上. mask: 必选 这部分是关于所应用的蒙版图像文件. n: 可选,默认 1 如上 size: 可选,默认 1024x1024 如上 response_format: 可选. 默认是 “url” 如上 Audio files声音文件 OpenAI 管理的不仅仅是图像。我们还可以使用音频文件来获取所提供录音的转录或翻译。这种方法使用 Whisper 模型,可以区分专有名词、品牌和俚语,从而提供正确的转录和翻译。例如,将 "微型机器 "作为一个品牌来谈论,与将 "微型机器 "作为一个普通名词翻译成西班牙语是不一样的。下面的例子是对 80 年代一个著名广告插播的转录: 因此,指示 Whisper 为我们转录音频的结果如下: { "text": "This is the Micromachine Man presenting the most midget miniature motorcade of micromachines. Each one has dramatic details, terrific trim, precision paint jobs, plus incredible micromachine pocket playsets. There's a police station, fire station, restaurant, service station, and more. Perfect pocket portables to take anyplace. And there are many miniature playsets to play with and each one comes with its own special edition micromachine vehicle and fun fantastic features that miraculously move. Raise the boat lift at the airport, marina, man the gun turret at the army base, clean your car at the car wash, raise the toll bridge. And these playsets fit together to form a micromachine world. Micromachine pocket playsets, so tremendously tiny, so perfectly precise, so dazzlingly detailed, you'll want to pocket them all. Micromachines and micromachine pocket playsets sold separately from Galoob. The smaller they are, the better they are." } 多么神奇! 你觉得呢? 之所以能取得上述成果,是因为 Whisper 模型接受了训练。我们可以从 OpenAI 页面提供的下图中看到一些相关信息。 更多信息可以访问 https://openai.com/research/whisper 请记住,告知程序文件名至关重要,因为服务需要知道它正在处理的文件类型(如 WAV、MP3、OGG 等)。由于我们在调用中只包含 Base64 内容,因此还必须指明文件扩展名,以便用随机文本和建议的扩展名创建文件名。例如,St.OpenAi.Msg.Audio.AudioRequest 消息的 "类型 "属性可显示音频的种类: MP3、OGG、WAV、FLAC 等。 Endpoint: https://api.openai.com/v1/audio/transcriptions 通过这种方法,您可以将音频内容转录为有声语言。 输入参数如下: file: 必要 在这里,您可以指定要转录的音频文件(而不是文件名)。它支持以下格式: FLAC、MP3、MP4、MPEG、MPGA、M4A、OGG、WAV 或 WEBM model: 必要 用于转录的模型。目前只有 "whisper-1 "可用 language: 可选. 默认是音频语言. 如果指定的话,根据 ISO-639-1,可以提高准确率和延时. prompt: 可选. 这是一段可选的文字,用于引导模型的风格或延续上一段音频。此处的信息必须与音频语言一致。. response_format. 可选,默认为 “json”. 在这一部分中,您要明确转录输出的格式。请使用以下选项之一: "json"、"text"、"verbose_json"。 temperature: 可选,默认为 0. 采样温度应介于 0 和 1 之间。 0.8 等较高值会使输出更加随机,而 0.2 等较低值则会使输出更加集中和确定。如果设置为 0,模型将使用对数似然自动提高温度,直到达到特定阈值。 本方法的文档请参考 https://platform.openai.com/docs/api-reference/audio/createTranscription<. Endpoint: https://api.openai.com/v1/audio/translations 此方法可将音频内容翻译成英语。输入参数如下: file: 必要 它是您要翻译的音频文件(而不是文件名)。它支持以下格式: FLAC、MP3、MP4、MPEG、MPGA、M4A、OGG、WAV 或 WEBM model: 必要. 如上. prompt: 可选l. 这是一段可选的文字,用于引导模型的风格或延续上一段音频。此处的信息必须使用英语。 response_format. 可选. 默认是 “json”. 在这里,您可以用以下选项之一决定转录输出的格式: "json"、"text"、"verbose_json"。 temperature: 可选. 默认为 0. 如上 更多文档请查阅 https://platform.openai.com/docs/api-reference/audio/createTranscription. 下一步? 由于 OpenAi 在不断发展,下一次迭代将是将文本转换为音频的方法,以及其他一些新功能。如果您喜欢这篇文章,请记得点个 "赞"。