首页 文章 精选 留言 我的

精选列表

搜索[Cookie处理],共10000篇文章
优秀的个人博客,低调大师

hanlp自然语言处理包的人名识别代码解析

HanLP发射矩阵词典nr.txt中收录单字姓氏393个。袁义达在《中国的三大姓氏是如何统计出来的》文献中指出:当代中国100个常见姓氏中,集中了全国人口的87%,根据这一数据我们只保留nr.txt中的100个常见词语的姓氏角色,其他词语去掉其姓氏角色状态。过滤后,nr.txt中具有姓氏角色的单字共计97个。 列于下表:丁 万 乔 于 任 何 余 侯 傅 冯 刘 卢 史 叶 吕 吴 周 唐 夏 姚 姜 孔 孙 孟 宋 尹 崔 常 康 廖 张 彭 徐 戴 方 易 曹 曾 朱 李 杜 杨 林 梁 武 段 毛 江 汤 汪 沈 潘 熊 王 田 白 石 秦 程 罗 胡 苏 范 萧 董 蒋 薛 袁 许 谢 谭 贺 贾 赖 赵 邓 邱 邵 邹 郑 郝 郭 金 钟 钱 阎 陆 陈 雷 韩 顾 马 高 魏 黄 黎 龚 实验效果姓氏过滤前,各命名实体识别准确率nr 33%ns 83%nt 43%姓氏过滤后,各命名实体识别准确率nr 36%ns 83%nt 81%这里没有开层叠隐马预测机构名和地名,nt上升原因估计是由于很多不是人名的词语没被标为人名,那么nt的模式匹配规则匹配不上了,所以机构名准确率上来了。错误识别的人名,100个常用姓氏的不多,很多恐怕是HanLP里其他词表干预进来的。隐马一般用于分词和词性标注是比较好的,为什么通常的序列标注方法也就是BIEO方法直接用到实体识别不合适呢。用词性标注为例,每一个词它所对应的词性标记子集是有限的,而这个子集相对于词性标记全集来说是小的。但是到了实体识别则不一定,拿人名来说,除了姓氏以外,名字词语部分可以填充的词语是任意的,也就是说任何词语都有可能出现在中间位置,此时发射矩阵中的某些词实际上就没有太大意义了,因为它可能等可能的由BIEO标记发出,而如果指利用四种标记之间的转移概率信息来确定最优的标记序列势必就影响效果。因此,我们通过引入角色标记,实际上这就引入了先验知识,比如某些字只能由姓氏标记产生,某些字一般情况都充当名字首字,某些字一般情况都充当名字末字,通过给这些不同情况下的字集按照其出现的位置的分布和其语法意义做角色定义,可以缩小每种角色标记可发出的词语集合,也就是每种词语(字)所对应的标记集的大小,相当于使发射概率分布不是均匀分布,那么预测的准确性肯定就得到提高了。下边介绍一下HanLP人名识别的主要流程1.使用使用匹配法求出各种分词路径用变量wordNetAll存储2.用viterbi方法找到一条最优的分词路径,这里主要使用用户自定义词典以及核心词典,用序列变量vertexList存储。3.角色观察,也就是根据发射概率矩阵列出vertexList中每个词语可能对应的角色标记。roleObserve(...)方法实现。4.角色标注,利用viterbi方法求出最优角色标记序列。viterbiComputeSimply(...)方法实现。5.对角色序列进行模式匹配得到人名。模式匹配定义在NRPattern类中。 在精度要求比较高且时间紧的情况下,最好的提高准确率的方法为,只保留常用姓氏,只保留最可能的2gram角色标记模式。在做人名识别时还有一个注意的点,如果你的预测语料和训练语料完全在文体上差别很大,或者说你就是在公开的训练语料上训练而不在预测语料上训练的话,基本上上下文信息是没有用处的,甚至有可能上下文信息会给实体边界标注带来干扰,我想任何机器学习包括深度学习,不管是文本分类领域还是实体识别领域都会有这种泛化能力的问题,这种问题恐怕通过算法是没法解决的,如果可以解决那么任何语种任何领域都可以使用一种模型,一劳永逸了。

优秀的个人博客,低调大师

PB 级数据处理挑战,Kubernetes如何助力基因分析?

作者李鹏,原文首发于InfoQ,《容器混合云,Kubernetes 助力基因分析》 引言 James Watson 和 Francis Crick 于 1953 年发现了 DNA 的双螺旋结构,从此揭开了物种进化和遗传的神秘面纱,开启了人类对数字化遗传的认知,但是人类基因奥秘却是一点点被读懂的。 1956 年,一则癌症和染色体相关性的发现令整个癌症研究界震动:慢性骨髓性白血病(CML)患者的第 22 号染色体,比一般然明显短很多。二十余年后,学者们发现,9 号染色体的 Abl 基因,与 22 号染色体的 BCR 基因连到了一块,交错易位产生了一条 BCR-Abl 融合基因。BCR-Abl 蛋白一直处于活跃状态且不受控制,引发不受控的细胞分裂,从而导致癌症。 也就是说,只要细胞表达 BCR-Abl 蛋白,就有血癌风险。美国着手深入研究,并成

优秀的个人博客,低调大师

2018年,自然语言处理最全的应用与合作

2018年见证了 NLP 许多新的应用发展。Elvis Saravia 是计算语言学专家,也是2019 计算语言学会年度大会北美分部的项目委员之一。他在一份报告中总结出,NLP 不仅在聊天机器人和机器学习中有所突破,也在医疗健康、金融、法律和广告等行业中有崭新的表现。点击文章中的链接,可查看详细信息。 聊天机器人聊天机器人是一项非常重要的研究领域,因为包括了 NLP 所覆盖的几大目标。 这篇 Wired 文章,解释语音情感识别如何帮助机器与人类建立更加健康的关系。 梅赛德斯奔驰发布了聊天机器人 MBUX,据称能为顾客创造“最会聊天的汽车”,让人与汽车可以通过自然的对话进行聊天。 NLP 创业公司 Hugging Face 获得400万美元融资,打造情感智能聊天机器人。 Wired 还发布了一篇文章讨论 Facebook 的虚拟助理 M ,以及为何公司计划将其关闭。此前就有许多人认为,也许聊天机器人只是一个泡沫,因为目前的 NLP 和 AI 的技术水准还无法达到顾客的预期。 这篇文章讨论 Passage AI 如何使用 NLP 和深度学习技术来训练顶尖的聊天机器人,用英语、西班牙语和中文进行聊天。 谷歌研究人员开发了一系列技术,深化聊天中的语意文本相似度。 Mastercard 称,聊天银行也许已经成为主流。 艾伦 AI 研究院通过 Alexandria 项目开发具有常识的AI。 AskArvi 使用 NLP 和深度学习,理解顾客的需要,从而推荐合适的保险项目。 亚马逊的新技术和 API 将提供能够离线使用的机器学习工具。 Facebook 提交了一个电商聊天机器人的专利申请,以 NLP 为其核心技术。 谷歌发布 Google Duplex,用于进行自然聊天,通过电话实现“真实世界”任务。这项技术在谷歌2018 IO 大会发布。 医疗健康 Jessica Kent 探讨如何将 NLP 应用于电子医疗记录,精确分析并改善心脏衰竭的病人护理。 Anthem 与 doc.ai 合作,分析和预测病人的过敏模式。 MIT 研究人员打造了一个基于 AI 的众筹平台,打造一个可以分析药物与蛋白质的系统。 据一份新报告称,NLP 和 AI 将把医疗从线下服务,改变为不受医生地理位置限制的高质量服务。 DeepMind 称其开发了一项新技术,能自动探测和治疗视网膜疾病。 一种基于 NLP 的新文本挖掘技术,可以通过病人的生物标记来决定癌症治疗方案。 创业公司 Proven Beauty 使用 NLP 为顾客提供个人化的护肤产品线。 看 NLP 如何帮助改善医疗文档。 BrightSign 是一款智能手套,使得具有语言残疾的人能够更好地沟通。 一家医疗机构使用深度学习和计算机视觉技术在 CT 扫描中检测疾病,比人类肿瘤学家的速度快150倍。 看谷歌如何通过技术,提升人们的健康水平。 自动化心理治疗机器人 Woebot 获得A轮800万美元融资。 Stitch CEO 讨论如何通过数据来销售个人化时尚。 Linguamatics 提供基于文字药物发现和研究的工具库。 机器学习工具 谷歌发布 Cloud AutoML,目标是为大企业提供云端 AI 服务,这是谷歌普及 AI 使命的一部分。 谷歌 AI 发布 BigQuery ML,能让数据科学家在大规模结构化和半结构化数据库上使用机器学习模型。 Fast.ai 与 AWS Open Datasets 合作,标准化并发布开放数据库。 Facebook 通过多语言嵌入,提供更快速的翻译服务。 PyTorch Geometric 通过 PyTorch 进行几何深度学习。 简单的几项测试看出,最优秀的谷歌翻译也很肤浅。 Linguistics Agents Ltd. 发布了一个 NLP 平台,训练深度增强学习代理。 这里有一个简化电子游戏代码编写的 AI 工具。 谷歌 Brain 发布 Magenta.js,一个利用 TensorFlow.js 生成音乐和艺术内容的API。 谷歌发布谷歌文字语音转换,其基础是 DeepMind 开发的 WaveNet。 TensorFlow 1.9 和 TensorFlow 1.10.0 相继发布,TensorFlow 2.0 将于2019年初发布,在这个论坛可以看到新版本的预期特征。 PyTorch 主持了第一场开发者大会,讨论最新发布的 PyTorch 1.0 的研究和生产能力。 Intel 开源了名为 NLP Architect 的 Python 库。 Semantris 是一款基于 NLP 和机器学习的文字联想游戏。 金融、广告和法律 澳大利亚证券与投资委员会(ASIC)希望利用 NLP 加强管理公司和金融服务法律。 Tumi 使用 AI 和 NLP 进行目标营销。 华尔街和大型创业公司现在都下血本投资 NLP 和机器学习,用于为客户进行更好的投资,类似于一种自动化投资管理。 小型和大型律师事务所正在通过 AI 一决高下。 金融行业在使用机器学习和 NLP 来重新定义服务,开发新市场。 通过“数据转移项目”,谷歌希望实现数据移动化,包括给予用户完全的数据掌控。 更多的NLP故事 据称,DARPA 将在 AI Next Initiative 投资高达20亿美元,实现语境推理和问题解决能力。 著名教授及研究员 Pedro Domingos 计划成为纽约投资公司 D.E. Shaw 集团的管理总监,领导公司的机器学习工作。 微软最新的专利目标通过 NLP 将来电 ID 功能提升一个水准,系统将能够识别来电者的目标和行动。 使用 AI 改善呼叫中心服务的创业公司 Observe.ai 筹集800万美元资金,使用机器学习和 NLP 技术将呼叫中心体验自动化。 本文由阿里云云栖社区组织翻译。文章原标题《NLP highlights of 2018》,译者:炫,审校:袁虎。文章简译,更为详细的内容,请查看原文。

优秀的个人博客,低调大师

Mysql 流增量写入 Hdfs(二) --Storm + hdfs 的流式处理

一. 概述 上一篇我们介绍了如何将数据从 mysql 抛到 kafka,这次我们就专注于利用 storm 将数据写入到 hdfs 的过程,由于 storm 写入 hdfs 的可定制东西有些多,我们先不从 kafka 读取,而先自己定义一个 Spout 数据充当数据源,下章再进行整合。这里默认你是拥有一定的 storm 知识的基础,起码知道 Spout 和 bolt 是什么。 写入 hdfs 可以有以下的定制策略: 自定义写入文件的名字 定义写入内容格式 满足给定条件后更改写入的文件 更改写入文件时触发的 Action 本篇会先说明如何用 storm 写入 HDFS,写入过程一些 API 的描述,以及最后给定一个例子: storm 每接收到 10 个 Tuple 后就会改变 hdfs 写入文件,新文件的名字就是第几次改变。 ps:storm 版本:1.1.1 。Hadoop 版本:2.7.4 。 接下来我们首先看看 Storm 如何写入 HDFS 。 二. Storm 写入 HDFS Storm 官方有提供了相应的 API 让我们可以使用。可以通过创建 HdfsBolt 以及定义相应的规则,即可写入 HDFS 。 首先通过 maven 配置依赖以及插件。 <properties> <storm.version>1.1.1</storm.version> </properties> <dependencies> <dependency> <groupId>org.apache.storm</groupId> <artifactId>storm-core</artifactId> <version>${storm.version}</version> <!--<scope>provided</scope>--> <exclusions> <exclusion> <groupId>org.slf4j</groupId> <artifactId>log4j-over-slf4j</artifactId> </exclusion> </exclusions> </dependency> <dependency> <groupId>commons-collections</groupId> <artifactId>commons-collections</artifactId> <version>3.2.1</version> </dependency> <dependency> <groupId>com.google.guava</groupId> <artifactId>guava</artifactId> <version>15.0</version> </dependency> <!--hadoop模块--> <dependency> <groupId>org.apache.hadoop</groupId> <artifactId>hadoop-client</artifactId> <version>2.7.4</version> <exclusions> <exclusion> <groupId>org.slf4j</groupId> <artifactId>slf4j-log4j12</artifactId> </exclusion> </exclusions> </dependency> <dependency> <groupId>org.apache.hadoop</groupId> <artifactId>hadoop-hdfs</artifactId> <version>2.7.4</version> <exclusions> <exclusion> <groupId>org.slf4j</groupId> <artifactId>slf4j-log4j12</artifactId> </exclusion> </exclusions> </dependency> <!-- https://mvnrepository.com/artifact/org.apache.storm/storm-hdfs --> <dependency> <groupId>org.apache.storm</groupId> <artifactId>storm-hdfs</artifactId> <version>1.1.1</version> <!--<scope>test</scope>--> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <version>3.5.1</version> <configuration> <source>1.8</source> <target>1.8</target> </configuration> </plugin> <plugin> <groupId>org.codehaus.mojo</groupId> <artifactId>exec-maven-plugin</artifactId> <version>1.2.1</version> <executions> <execution> <goals> <goal>exec</goal> </goals> </execution> </executions> <configuration> <executable>java</executable> <includeProjectDependencies>true</includeProjectDependencies> <includePluginDependencies>false</includePluginDependencies> <classpathScope>compile</classpathScope> <mainClass>com.learningstorm.kafka.KafkaTopology</mainClass> </configuration> </plugin> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-shade-plugin</artifactId> <version>1.7</version> <configuration> <createDependencyReducedPom>true</createDependencyReducedPom> </configuration> <executions> <execution> <phase>package</phase> <goals> <goal>shade</goal> </goals> <configuration> <transformers> <transformer implementation="org.apache.maven.plugins.shade.resource.ServicesResourceTransformer"/> <transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer"> <mainClass></mainClass> </transformer> </transformers> </configuration> </execution> </executions> </plugin> </plugins> </build> 这里要提一下,如果要打包部署到集群上的话,打包的插件需要使用 maven-shade-plugin 这个插件,然后使用 maven Lifecycle 中的 package 打包。而不是用 Maven-assembly-plugin 插件进行打包。 因为使用 Maven-assembly-plugin 的时候,会将所有依赖的包unpack,然后在pack,这样就会出现,同样的文件被覆盖的情况。发布到集群上的时候就会报 No FileSystem for scheme: hdfs 的错 。 然后是使用 HdfsBolt 写入 Hdfs。这里来看看官方文档中的例子吧。 // 使用 "|" 来替代 ",",来进行字符分割 RecordFormat format = new DelimitedRecordFormat() .withFieldDelimiter("|"); // 每输入 1k 后将内容同步到 Hdfs 中 SyncPolicy syncPolicy = new CountSyncPolicy(1000); // 当文件大小达到 5MB ,转换写入文件,即写入到一个新的文件中 FileRotationPolicy rotationPolicy = new FileSizeRotationPolicy(5.0f, Units.MB); //当转换写入文件时,生成新文件的名字并使用 FileNameFormat fileNameFormat = new DefaultFileNameFormat() .withPath("/foo/"); HdfsBolt bolt = new HdfsBolt() .withFsUrl("hdfs://localhost:9000") .withFileNameFormat(fileNameFormat) .withRecordFormat(format) .withRotationPolicy(rotationPolicy) .withSyncPolicy(syncPolicy); //生成该 bolt topologyBuilder.setBolt("hdfsBolt", bolt, 5).globalGrouping("randomStrSpout"); 到这里就结束了。可以将 HdfsBolt 当作一个 Storm 中特殊一些的 bolt 即可。这个 bolt 的作用即使根据接收信息写入 Hdfs。 而在新建 HdfsBolt 中,Storm 为我们提供了相当强的灵活性,我们可以定义一些策略,比如当达成某个条件的时候转换写入文件,新写入文件的名字,写入时候的分隔符等等。 如果选择使用的话,Storm 有提供部分接口供我们使用,但如果我们觉得不够丰富也可以自定义相应的类。下面我们看看如何控制这些策略吧。 RecordFormat 这是一个接口,允许你自由定义接收到内容的格式。 public interface RecordFormat extends Serializable { byte[] format(Tuple tuple); } Storm 提供了 DelimitedRecordFormat ,使用方法在上面已经有了。这个类默认的分割符是逗号",",而你可以通过 withFieldDelimiter 方法改变分隔符。如果你的初始分隔符不是逗号的话,那么也可以重写写一个类实现 RecordFormat 接口即可。 FileNameFormat 同样是一个接口。 public interface FileNameFormat extends Serializable { void prepare(Map conf, TopologyContext topologyContext); String getName(long rotation, long timeStamp); String getPath(); } Storm 所提供的默认的是 org.apache.storm.hdfs.format.DefaultFileNameFormat 。默认人使用的转换文件名有点长,格式是这样的: {prefix}{componentId}-{taskId}-{rotationNum}-{timestamp}{extension} 例如: MyBolt-5-7-1390579837830.txt 默认情况下,前缀是空的,扩展标识是".txt"。 SyncPolicy 同步策略允许你将 buffered data 缓冲到 Hdfs 文件中(从而client可以读取数据),通过实现org.apache.storm.hdfs.sync.SyncPolicy 接口: public interface SyncPolicy extends Serializable { boolean mark(Tuple tuple, long offset); void reset(); } FileRotationPolicy 这个接口允许你控制什么情况下转换写入文件。 public interface FileRotationPolicy extends Serializable { boolean mark(Tuple tuple, long offset); void reset(); } Storm 有提供三个实现该接口的类: 最简单的就是不进行转换的org.apache.storm.hdfs.bolt.rotation.NoRotationPolicy ,就是什么也不干。 通过文件大小触发转换的 org.apache.storm.hdfs.bolt.rotation.FileSizeRotationPolicy。 通过时间条件来触发转换的 org.apache.storm.hdfs.bolt.rotation.TimedRotationPolicy。 如果有更加复杂的需求也可以自己定义。 RotationAction 这个主要是提供一个或多个 hook ,可加可不加。主要是在触发写入文件转换的时候会启动。 public interface RotationAction extends Serializable { void execute(FileSystem fileSystem, Path filePath) throws IOException; } 三.实现一个例子 了解了上面的情况后,我们会实现一个例子,根据写入记录的多少来控制写入转换(改变写入的文件),并且转换后文件的名字表示当前是第几次转换。 首先来看看 HdfsBolt 的内容: RecordFormat format = new DelimitedRecordFormat().withFieldDelimiter(" "); // sync the filesystem after every 1k tuples SyncPolicy syncPolicy = new CountSyncPolicy(1000); // FileRotationPolicy rotationPolicy = new FileSizeRotationPolicy(1.0f, FileSizeRotationPolicy.Units.KB); /** rotate file with Date,every month create a new file * format:yyyymm.txt */ FileRotationPolicy rotationPolicy = new CountStrRotationPolicy(); FileNameFormat fileNameFormat = new TimesFileNameFormat().withPath("/test/"); RotationAction action = new NewFileAction(); HdfsBolt bolt = new HdfsBolt() .withFsUrl("hdfs://127.0.0.1:9000") .withFileNameFormat(fileNameFormat) .withRecordFormat(format) .withRotationPolicy(rotationPolicy) .withSyncPolicy(syncPolicy) .addRotationAction(action); 然后分别来看各个策略的类。 FileRotationPolicy import org.apache.storm.hdfs.bolt.rotation.FileRotationPolicy; import org.apache.storm.tuple.Tuple; import java.text.SimpleDateFormat; import java.util.Date; /** * 计数以改变Hdfs写入文件的位置,当写入10次的时候,则更改写入文件,更改名字取决于 “TimesFileNameFormat” * 这个类是线程安全 */ public class CountStrRotationPolicy implements FileRotationPolicy { private SimpleDateFormat df = new SimpleDateFormat("yyyyMM"); private String date = null; private int count = 0; public CountStrRotationPolicy(){ this.date = df.format(new Date()); // this.date = df.format(new Date()); } /** * Called for every tuple the HdfsBolt executes. * * @param tuple The tuple executed. * @param offset current offset of file being written * @return true if a file rotation should be performed */ @Override public boolean mark(Tuple tuple, long offset) { count ++; if(count == 10) { System.out.print("num :" +count + " "); count = 0; return true; } else { return false; } } /** * Called after the HdfsBolt rotates a file. */ @Override public void reset() { } @Override public FileRotationPolicy copy() { return new CountStrRotationPolicy(); } } FileNameFormat import org.apache.storm.hdfs.bolt.format.FileNameFormat; import org.apache.storm.task.TopologyContext; import java.util.Map; /** * 决定重新写入文件时候的名字 * 这里会返回是第几次转换写入文件,将这个第几次做为文件名 */ public class TimesFileNameFormat implements FileNameFormat { //默认路径 private String path = "/storm"; //默认后缀 private String extension = ".txt"; private Long times = new Long(0); public TimesFileNameFormat withPath(String path){ this.path = path; return this; } @Override public void prepare(Map conf, TopologyContext topologyContext) { } @Override public String getName(long rotation, long timeStamp) { times ++ ; //返回文件名,文件名为更换写入文件次数 return times.toString() + this.extension; } public String getPath(){ return this.path; } } RotationAction import org.apache.hadoop.fs.FileContext; import org.apache.hadoop.fs.FileSystem; import org.apache.hadoop.fs.Path; import org.apache.storm.hdfs.common.rotation.RotationAction; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.io.IOException; import java.net.URI; /** 当转换写入文件时候调用的 hook ,这里仅写入日志。 */ public class NewFileAction implements RotationAction { private static final Logger LOG = LoggerFactory.getLogger(NewFileAction.class); @Override public void execute(FileSystem fileSystem, Path filePath) throws IOException { LOG.info("Hdfs change the written file!!"); return; } } OK,这样就大功告成了。通过上面的代码,每接收到 10 个 Tuple 后就会转换写入文件,新文件的名字就是第几次转换。 完整代码包括一个随机生成字符串的 Spout ,可以到我的 github 上查看。 StormHdfsDemo:https://github.com/shezhiming/StormHdfsDemo 更多干货,欢迎关注公众号,哈尔的数据城堡。

资源下载

更多资源
Nacos

Nacos

Nacos /nɑ:kəʊs/ 是 Dynamic Naming and Configuration Service 的首字母简称,一个易于构建 AI Agent 应用的动态服务发现、配置管理和AI智能体管理平台。Nacos 致力于帮助您发现、配置和管理微服务及AI智能体应用。Nacos 提供了一组简单易用的特性集,帮助您快速实现动态服务发现、服务配置、服务元数据、流量管理。Nacos 帮助您更敏捷和容易地构建、交付和管理微服务平台。

Spring

Spring

Spring框架(Spring Framework)是由Rod Johnson于2002年提出的开源Java企业级应用框架,旨在通过使用JavaBean替代传统EJB实现方式降低企业级编程开发的复杂性。该框架基于简单性、可测试性和松耦合性设计理念,提供核心容器、应用上下文、数据访问集成等模块,支持整合Hibernate、Struts等第三方框架,其适用范围不仅限于服务器端开发,绝大多数Java应用均可从中受益。

Rocky Linux

Rocky Linux

Rocky Linux(中文名:洛基)是由Gregory Kurtzer于2020年12月发起的企业级Linux发行版,作为CentOS稳定版停止维护后与RHEL(Red Hat Enterprise Linux)完全兼容的开源替代方案,由社区拥有并管理,支持x86_64、aarch64等架构。其通过重新编译RHEL源代码提供长期稳定性,采用模块化包装和SELinux安全架构,默认包含GNOME桌面环境及XFS文件系统,支持十年生命周期更新。

WebStorm

WebStorm

WebStorm 是jetbrains公司旗下一款JavaScript 开发工具。目前已经被广大中国JS开发者誉为“Web前端开发神器”、“最强大的HTML5编辑器”、“最智能的JavaScript IDE”等。与IntelliJ IDEA同源,继承了IntelliJ IDEA强大的JS部分的功能。

用户登录
用户注册