聪明的知识库

enriquepablo的Python项目详细描述


术语知识库

术语是知识库。 它提供了一种声明性语言来表达和查询知识。 术语的主要用途是 依赖于术语语言: 据说它非常有力和简洁, 同时非常可读, 非常接近自然语言。

条款是根据GPLv3授权的,托管在 github

术语语言

在这里我将描述术语语言。 它是一种声明性逻辑语言。 有了它,您可以:

  • 定义新词(名词、动词和名称);
  • 用定义好的词来构建事实;
  • 建立规则,将给定的事实组合起来生成新的事实;
  • 执行复杂的查询。

术语语言与其他逻辑语言相似, 例如prolog或clips (它更靠近夹子,因为它是前链式的, 基于RETE网络)。 但在某种意义上它更具表现力, 因为所有定义的项(或词) 具有相同的类别。 在术语上,你建立句子或事实, 有一个动词(即一个词)和任意数量的宾语, 这些对象可以是任何类型的词: 名字,动词,名词,甚至其他事实。 相反,要在prolog中构建事实, 你用一种特殊的动词,一个谓语, 不能作为争论术语 (在序言中相当于一个对象)。 换句话说,规则可以有一个逻辑变量 涵盖任何事实或术语,包括动词, 在(惯用的)序言中不可能做到的事情。

我想说的是,这种差异给了我们条件 足够的边缘以便通常有用。

无论如何,术语是基于一阶理论的, 在有限的宇宙中解释, 所以可以在prolog中实现; 这就是为什么我指定"惯用的"。

要尝试下面给出的示例,如果您安装了terms, 你必须在终端机里输入"术语", 您将得到一个repl,在这里您可以输入terms结构。 要安装术语,请遵循install.rst中的说明。

这里可以找到更多的例子 而在 Github存储库

单词

术语结构的主要组成部分是单词。

首先,有几个预定义的单词: 单词, 动词 名词 数字 事物 存在

新单词的定义是将它们与现有单词相关联。

两个词之间可以建立两种关系。

我们将在下面看到, 这些关系在形式上类似于集合论关系 "是"的元素,"是"的子集。

在英语中,我们把第一种关系表示为"是类型的", 它表示为:

word1 is a word2.

所以我们可以说 word1 word2 类型, 根据单词2定义 word1 (因此, word2 必须在之前定义,或者是预定义的)。 第二种关系用英语表示为"is subtype of", 在术语上:

a word1 is a word2.

因此,我们可以说 word1 word2 的一个子类型, 还定义了 word1 word2 方面。 在预定义的单词中,给出了这些关系:

word is a word.
verb is a word.
a verb is a word.
noun is a word.
a noun is a word.
thing is a noun.
a thing is a word.
exist is a verb.
a exist is a word.
number is a word.
a number is a word.

要定义一个新词,你要把它和一个已有的词联系起来。例如:

a person is a thing.
a man is a person.
a woman is a person.
john is a man.
sue is a woman.

这些关系具有连续性,由两个隐式规则给出:

A is a B; a B is a C -> A is a C.
a A is a B; a B is a C -> a A is a C.

因此,从以上所有方面来看,例如,我们有:

thing is a word.
person is a word.
person is a noun.
john is a word.
a man is a thing.
john is a thing.
sue is a person.
...

用语言,我们可以建立事实。 一个事实由一个动词和任意数量的(带标签的)对象组成。

动词是特殊的词,因为它们决定 事实的修正者他们。 这些修饰语是单词,并且有标签。 要定义一个新动词, 你先提供一个祖先动词 (或由冒号分隔的一系列祖先动词) 事实上,可以作为动词修饰语的词的类型, 与他们的标签相关。 例如:

to love is to exist, subj a person, who a person.

可以理解为: 爱被定义为存在的一个子类型, 当用于事实时,它可以接受一个 类型的主题person 以及一个标记为"谁"的对象,也属于"人"类型。

原语动词是exist, 它只是定义了一个类型为thing的subj对象。 有更多预定义的动词, 当我们用术语解释时间的处理时,我们将看到它的用途。

事实

事实是由一个动词和一些宾语构成的。 它们在括号里。例如,我们可能有这样一个事实:

(love john, who sue).

主语宾语是特殊的:所有动词都有它, 事实上,它没有标上 subj , 它只是在动词之后取代主语。

动词继承其祖先的宾语类型。原语动词存在 只接受一个对象, subj ,类型为 word ,由所有其他动词继承。 所以,如果我们定义一个动词:

to adore is to love.

它将有一个类型为person的对象。如果爱慕提供了 一个新的对象,它会被添加到继承的对象中。 新动词可以重写继承的对象类型,以提供原始对象的子类型 对象类型 (就像我们在上面对subj所做的那样;subj被预定义为 word 类型)

事实就是语言, "一等公民", 可以用在任何可以用词的地方。 事实是存在类型的词,也是动词类型的词, was<;verb>;是用于构建事实的动词。 所以我们的事实是 (爱约翰,谁休)是爱。

事实上,对象可以是任何类型的(a word ,a verb ,a noun ,a thing , a 数字 )。此外,它们也可以是事实(类型 exist )。 所以,如果我们定义一个动词,比如:

word1 is a word2.
0

然后我们可以建立如下事实:

word1 is a word2.
1

事实上:

word1 is a word2.
2

规则

我们可以建立规则,在现有(或新添加的)规则的基础上生成新的事实。 一条规则有两组事实,条件(先给出)和连续性。每一组的事实 事实用分号(连词)分隔,符号 ->; (含义)分隔条件 从圣餐中。 一个简单的规则可能是:

word1 is a word2.
3

知识库中的事实与规则的条件相匹配, 当一条规则的所有条件都符合一致的事实时, 这些连续性被添加到知识库中。所需的连贯性 匹配事实中涉及条件中的变量。

我们可以在规则中使用变量。它们是逻辑变量,只用于匹配单词, 范围仅限于使用的规则。我们通过 将它可以匹配的单词类型的名称大写,并附加任意数量的 数字。例如,变量person1可以匹配任何人,比如 约翰 。对于变量,我们可以建立如下规则:

word1 is a word2.
4

如果我们有这个规则,而且还有这个规则,系统将得出结论 (爱苏,约翰)。

变量可以匹配整个事实。例如,用我们定义的动词,我们可以 建立一个规则,例如:

word1 is a word2.
5

有了这个,和 (想要john,what(love sue,who john))。 ,系统将得出结论 (爱苏,约翰)。

与动词(或名词)匹配的变量有一种特殊的形式,即它们的前缀是 动词(或名词)的名称,以便h动词(或名词),是前缀动词(或名词)的子类型。 例如,使用上面的单词,我们可以制定一个规则,例如:

word1 is a word2.
6

在本例中, loveverb1 将同时匹配 love adore ,因此两者都匹配 (爱约翰,谁起诉) (爱约翰,谁起诉) 会得出结论 (爱苏,谁约翰)或(爱苏,谁约翰)。

对于更详细的示例,我们可以定义一个新动词:

word1 is a word2.
7

还有一条规则:

word1 is a word2.
8

然后, (允许约翰去崇拜) 会让他去崇拜,而不是去爱。

我们可以使用与任何单词或事实匹配的单词变量,例如 word1

在条件下,我们可能需要匹配一个完整的事实,同时匹配一些 它的组成词。为此,我们在事实前加上名字 用冒号分隔的事实变量。这样,上述规则将变为:

word1 is a word2.
9

整数

整数的类型是 数字 。 我们不定义数字,只是用数字。 在python中可以转换为整数类型的任何字符序列 是数字,例如: 1

数字变量只由一个大写字母和一个整数组成,如 n1 p3 ,或 f122

蟒蛇状态

在规则中,我们可以添加一个用python测试条件的部分,或者在其中生成 现有变量之外的新变量。这主要用于测试算术条件 以及执行算术运算。本节是在条件之后放置的, 在符号之间。测试结果放在 条件 python变量,如果其计算结果为 false ,则不会触发规则。

举个例子,让我们设想一些新术语:

a word1 is a word2.
0

现在,我们可以建立一个规则,例如:

a word1 is a word2.
1

如果我们有:

a word1 is a word2.
2

系统将(仅)断定 (john输入,其中 俱乐部重大事件)

否定

我们可以使用两种否定,古典否定和 失败否定。

经典否定

任何事实都可以通过前置 来否定! 到动词:

a word1 is a word2.
3

否定的事实和非否定的事实是一样的。 只有否定的事实才能与否定的事实相匹配, 它们可以在规则中断言或使用。 否定的唯一特殊之处是 制度不允许事实及其否定 在同一个知识库中:它将警告矛盾 会拒绝冒犯的事实。

失败否定

在pythonic条件下,我们可以使用函数runtime.count 有一个字符串参数,一个术语事实(可能有变量), 它将返回数据库中与给定事实匹配的事实数。 我们可以用这个来检验 在知识库中,因此会因失败而否定。

必须小心使用 count 函数。 如果输入的事实可能符合pythonic count 条件, 它本身决不会触发任何规则。 规则由符合正常条件的事实激活; 而pythonic条件只能允许或中止 那些激活。 换句话说,当一个事实被添加, 它是在所有规则的正常条件下测试的, 如果它激活了任何规则,就会测试蟒蛇的情况。 可以看到这种行为的一个例子 这里 。 如果您检查上一个链接中的本体, 你会发现这显然是错误的; 这就是我说必须小心的原因。 数数是及时的, 不建议在没有激活时间的情况下使用它。

时间

在我们迄今为止描述的单调经典逻辑中, 表示物理时间非常简单: 您只需添加一个 时间 类型的对象 数字 任何时态动词。 然而,代表现在,代表现在, 也就是说,一个不断变化的、与众不同的瞬间, 这种逻辑是不够的。 我们需要用一些非单调的技巧, 作为一种时间逻辑来实现的。 此时间逻辑可以在设置文件中激活:

a word1 is a word2.
4

如果它被激活,会发生几种情况。

首先,系统开始跟踪当前时间: 它有一个整数寄存器,其值表示当前时间。 此寄存器每秒钟更新一次。 模式有3个可能值 时间设置: 如果设置为 ,则不随时间变化。 如果设置为 normal ,则更新时系统的当前时间将增加1。 如果设置为实际值,则系统的当前时间 使用python的 导入时间; int(time.time()) 更新。

第二件事是,与其定义扩展 的动词exist , 我们使用了两个新动词, 出现 忍受 ,这两个类型都存在 。 这些新动词有特殊的宾语: 发生 有一个 对象,并且 起持续 a 直到 对象。

三是系统开始保留两个不同的事实集, 一个代表现在,一个代表过去。 所有推理都发生在当前事实集中。 当我们添加用这些动词生成的事实时,系统会自动添加 在物体上发生,在物体上忍受, 两者都有其"现在"寄存器的值。 忍耐事实的 对象没有定义。 我们从未明确设置过这些对象。 每次更新时间时,所有 发生的事实都会从当前删除 加上过去的事实,因此停止产生连续性。 如果我们在查询中指定一个 如果不提供 at 对象,则返回当前。 这同样适用于 忍受事实,用 起代替 处。 我们可以说,当前事实集中的"忍受"事实 现在进行时。

当我们激活时间逻辑时发生的第四件事 我们可以在规则的连续性中使用一个新的谓词: 完成 。这个动词的定义如下:

a word1 is a word2.
5

当一个连续的规则被激活时, 它从当前事实集中获取所提供的事实, 以当前时间为值向其添加一个 直到 对象, 将其从当前事实集中移除, 并将其添加到过去的事实集。

还有时态动词exclusive pertence,subub of the pertence。 排他性持久性的特点是 这样的动词被添加到知识库中, 任何先前出现的主语和动词相同的事实都是完成的。

另一个动词,cocure ,源自cocure ,它的奇点是, 当一个事实作为其他事实的连续体被添加,并被构建 从 派生的动词happen ,通过管道反馈到 用户添加产生连续性的事实。

查询

查询是由分号分隔的事实集, 有或没有变量。 如果查询不包含变量,则答案将为 true 是否存在所要求的事实,或是否存在所要求的事实。 要找出一个事实是否被否定,我们必须查询它的否定。

如果我们在查询中包含变量, 我们将得到所有的变量替换 这将产生一个 true 查询, 以字符串映射的json列表的形式。

但是,我们不能添加特殊约束, 就像我们在蟒蛇状态下的规则一样。

其他技术说明。

  • 我展示了几种不同的变量, 对于事物,对于动词,对于数字,对于事实。 但术语背后的逻辑是一阶的, 只有一种人, 以及各种变量的扩散 只是语法上的糖。 人1 相当于 "对所有X来说,X是一个人,X…"。 loveverb1相当于 "对所有X来说,X是爱,X…"
  • 系统的设计是这样的 两者都增加了新的事实(以其神圣性) 对事实的质疑应该独立于 知识库的大小。 我们唯一依赖数据大小的地方 在算术条件下, 因为目前数字对象本身没有索引。
  • 规则的python部分是exec 在本地变量中使用带有``condition 变量的dict 还有一句空话,是全球性的。我们可以加上 例如,numpy。

条款协议

一旦您有了知识库并运行了kb守护进程:

a word1 is a word2.
6

通过TCP套接字(例如telnet)与之通信, 我将在这里描述一个通信协议。

在这个协议中,从客户端到守护进程的消息是 utf8编码字节字符串,由字符串 'finish-terms'终止

守护进程连接这些字符串,并且根据头的不同, 做一些事情。 头是小写字母alfabetic字符的字符串, 用冒号与消息的其余部分隔开。

  • 如果没有标题,则假定消息是 语言中的一系列结构, 并反馈给编译器。 根据构造的类型,响应可以不同:
    • 如果构造是一个查询,则响应是一个json字符串 后跟字符串 'end'
    • 如果构造是定义、事实和/或规则, 答案是一系列的事实 进入建筑的连续性 动词 将发生在 ,以字符串 'end' 结尾
  • 如果有一个 lexicon: 头,则响应是一个json字符串 后跟字符串 'end' 。json的内容取决于 在第二个标题上:
    • 获取子单词 返回作为子单词的单词名称列表 其名称在标题后面的单词。
    • 获取单词: 返回单词名列表 其名称在标题后的单词类型。
    • 获取谓词: 返回谓词 以标题命名。对于每个对象,都有一个列表 3项:
      • 带有标签名称的字符串;
      • 具有对象类型名称的字符串;
      • 表示对象本身必须是事实的布尔值。
  • 如果有 编译器: 头:
    • 如果有一个 exec_globals: 头,则后面的字符串 假设是一名全球执行官,并以此身份输入知识库。
    • 如果有一个 术语: 标题,则假定如下 术语构成,我们回到本系列的第一个要点。

安装和使用

使用setuptools在virtualenv上安装

<你不需要用蟒蛇, 但您必须确保使用的是Python3.3.0或更高版本:

a word1 is a word2.
7

制作一个virtualenv,然后安装setuptools:

a word1 is a word2.
8

安装术语(在本例中,支持PostgreSQL):

a word1 is a word2.
9

在干净的debian机器上安装buildout

我用这个来发展术语。

从一个干净的基本Debian7.1虚拟机开始, 仅选择"标准系统实用程序"和 "ssh服务器"软件在安装过程中。

一些附加软件,首先编译python-3.3:

word is a word.
verb is a word.
a verb is a word.
noun is a word.
a noun is a word.
thing is a noun.
a thing is a word.
exist is a verb.
a exist is a word.
number is a word.
a number is a word.
0

安装git和rdbms:

word is a word.
verb is a word.
a verb is a word.
noun is a word.
a noun is a word.
thing is a noun.
a thing is a word.
exist is a verb.
a exist is a word.
number is a word.
a number is a word.
1

允许方法"信任"到PostgreSQL的所有本地连接,并创建一个"terms"用户:

word is a word.
verb is a word.
a verb is a word.
noun is a word.
a noun is a word.
thing is a noun.
a thing is a word.
exist is a verb.
a exist is a word.
number is a word.
a number is a word.
2

获取构建:

word is a word.
verb is a word.
a verb is a word.
noun is a word.
a noun is a word.
thing is a noun.
a thing is a word.
exist is a verb.
a exist is a word.
number is a word.
a number is a word.
3

制作一个python-3.3.2虚拟版:

word is a word.
verb is a word.
a verb is a word.
noun is a word.
a noun is a word.
thing is a noun.
a thing is a word.
exist is a verb.
a exist is a word.
number is a word.
a number is a word.
4

编辑配置文件并运行构建 (如果更改配置文件, 必须重新运行构建):

word is a word.
verb is a word.
a verb is a word.
noun is a word.
a noun is a word.
thing is a noun.
a thing is a word.
exist is a verb.
a exist is a word.
number is a word.
a number is a word.
5

现在我们初始化知识库,并启动守护进程:

word is a word.
verb is a word.
a verb is a word.
noun is a word.
a noun is a word.
thing is a noun.
a thing is a word.
exist is a verb.
a exist is a word.
number is a word.
a number is a word.
6

现在,您可以启动REPL并使用它:

word is a word.
verb is a word.
a verb is a word.
noun is a word.
a noun is a word.
thing is a noun.
a thing is a word.
exist is a verb.
a exist is a word.
number is a word.
a number is a word.
7

与术语接口

安装后,您应该有一个 术语 脚本, 它提供了一个repl。

如果您只是在命令行中键入 terms , 你会得到一个命令行解释器, 绑定到内存中的sqlite数据库。

如果你想让你的术语知识库持久化, 必须编辑配置文件, 并为知识库添加一个部分。 如果您安装了易安装的条款, 必须在 ~/.terms.cfg中创建此配置文件

word is a word.
verb is a word.
a verb is a word.
noun is a word.
a noun is a word.
thing is a noun.
a thing is a word.
exist is a verb.
a exist is a word.
number is a word.
a number is a word.
8

然后必须初始化知识库:

word is a word.
verb is a word.
a verb is a word.
noun is a word.
a noun is a word.
thing is a noun.
a thing is a word.
exist is a verb.
a exist is a word.
number is a word.
a number is a word.
9

现在您可以启动repl:

a person is a thing.
a man is a person.
a woman is a person.
john is a man.
sue is a woman.
0

在配置文件中,您可以将 部分(例如, [mykb] )根据您的喜好, 每个知识库一个。

使用PostgreSQL

要使用postgresql,需要psycopg2包, 你可以通过简单的安装。当然, 您需要postgresql及其头文件:

a person is a thing.
a man is a person.
a woman is a person.
john is a man.
sue is a woman.
1

如果使用 波斯特雷斯克 和用户(在dbms url的配置文件中指定) 必须能够创建和删除表和索引。 您将拥有如下配置文件:

a person is a thing.
a man is a person.
a woman is a person.
john is a man.
sue is a woman.
2

例如,设置好后,打开repl:

a person is a thing.
a man is a person.
a woman is a person.
john is a man.
sue is a woman.
3

使用kbdaemon

terms提供了一个监听tcp端口1967的守护进程。 要使用守护程序,必须将配置放在名为"default"的配置文件的一节中:

a person is a thing.
a man is a person.
a woman is a person.
john is a man.
sue is a woman.
4

现在您可以启动守护程序:

a person is a thing.
a man is a person.
a woman is a person.
john is a man.
sue is a woman.
5

你可以通过TCP连接到机器的1967端口 并使用readme.rst.末尾描述的协议。

支架

在google groups上有一个邮件列表。 您还可以在跟踪程序中打开问题。 或者在谷歌的邮件域给我发邮件<;enriquepablo>;

欢迎加入QQ群-->: 979659372 Python中文网_新手群

推荐PyPI第三方库


热门话题
JAXB可以将ArrayList作为逗号分隔的值输出吗?   java使用bcel将一个内部类移动到另一个外部类   java无法识别Lucene MoreLikeThis中的错误   安卓如何在Frida中将动态类转换为json或java文件   java如何使用Struts2在blob类型的列中保存我的sql中的图像?   使用mavenreleaseplugin将java maven发布到nexus 3.0.1失败   java这是正确的方法吗?   Windows上的java Runner不工作   找不到java Hibernate+Spring xml映射   java如何访问WMI查询的数据(通过JNA)SAFEARRAY结果   java如何在本地导入库而不使用Maven中的Nexus?   java渐变本地项目依赖项   使用URLFetchService/URL Google appengine for java