您可能还喜欢:
在 Neoj4 中构建聊天机器人

在第一部分,我们学会了倾听我们的用户,在第二部分,我们开始学习如何回话。在我们进一步进入存储过程之前,我们建立一个小前端来展示我们到目前为止在这个概念验证方面所做的工作,怎么样?这也将使事情更容易测试,让我们进入用户的心态。

这里有大量的选择,很多人喜欢春天和春天的靴子。其他人更时髦,进入米考特。我更是一个时髦的人,更喜欢使用乔比,但没关系。我们将使用 Cypher、Neo4j 驱动程序和沿途构建的存储程序,因此从技术上讲,您可以使用任何语言执行此操作。

我不是设计师,所以我在网上搜索了一个简单的聊天平台主题,并发现”刷卡:最简单的聊天平台”为19美元。这将节省我大量的时间与CSS,我认为这是网络开发的黑暗魔力。

Jooby项目开始非常简单,请遵循文档,您最终会得到类似的东西:


import io.jooby.Jooby;

public class App extends Jooby {

  {
    get("/", ctx -> "Welcome to Jooby!");
  }

  public static void main(String[] args) {
    runApp(args, App::new);
  }
}

我们不想欢迎人们来到Jooby,我们希望让他们试用我们的聊天机器人应用程序,所以让我们改变该文本,而不是要求用户登录注册:

get("/", ctx -> views.index.template());
get("/register", ctx -> views.register.template());


在我们更进一步之前,我们需要能够与Neo4j交谈。我们需要告诉它,一个用户正在尝试注册,我们将新4jJava驱动程序添加到pom.xml文件,并建立一个小的Jooby扩展。Neo4jExtension将使用配置的 URI、用户名和密码连接到 Neo4j,然后将驱动程序注册到应用程序

获取环境();
配置 conf = env.getConfig();

驱动程序 = 图形数据库.驱动程序(conf.getString(”neo4j.uri”)
AuthTokens.basic(conf.getString(”neo4j.用户名”)
conf.getString(”新4j.密码”));

服务注册表 = 应用程序.getServices();
注册表.put(驱动程序类,驱动程序);
应用程序.onStop(驱动程序);
}

}

现在我们需要编写后寄存器终结点。我们的表单会传递用户的 ID、密码和电话号码。我们将加密密码,要求 Neo4j 驱动程序,并使用它发送一个 Cypher 查询到 Neo4j 以创建用户。


        post("/register", ctx -> {
            Formdata form = ctx.form();
            String id = form.get("id").toOptional().orElse("");
            String password = form.get("password").toOptional().orElse("");
            String phone = form.get("phone").toOptional().orElse("");
            password = BCrypt.hashpw(password, BCrypt.gensalt());
            Driver driver = require(Driver.class);
            Map<String, Object> user = CypherQueries.CreateMember(driver, id, phone, password);

有些人喜欢在代码库中进行 Cypher 查询。我有点喜欢让他们大多挤在一起。因此,我们将创建一个CypherQueries接口,其中将粘它们现在。我们还需要一些帮助方法。一个是从我们的驱动程序创建会话并执行给定一组参数的查询,并返回映射迭代器,以便更轻松地处理:


    static Iterator<Map<String, Object>> query(Driver driver, String query, 
                                               Map<String, Object> params) {
        try (Session session = driver.session()) {
            List<Map<String, Object>> list = session.run(query, params)
                    .list( r -> r.asMap(CypherQueries::convert));
            return list.iterator();
        }
    }

以易于转换为地图的方式恢复所有内容的转换方法:


    static Object convert(Value value) {
        switch (value.type().name()) {
            case "PATH":
                return value.asList(CypherQueries::convert);
            case "NODE":
            case "RELATIONSHIP":
                return value.asMap();
        }
        return value.asObject();
    }

有了管道的方式,我们可以得到什么需要。用于创建帐户和成员的密码查询:


String createMember = "CREATE (a:Account { id: $id, password: $password })
                              -[:HAS_MEMBER]->(member:Member { phone: $phone }) 
RETURN a.id AS id, member.phone AS phone";

…和把东西绑在一起的方法


    static Map<String, Object> CreateMember(Driver driver, String id, 
                                            String phone, String password) {
        Map<String, Object> response = Iterators.singleOrNull(query(driver, createMember,
                {{
                    put("id", id);
                    put("phone", phone);
                    put("password", password); }}
            ));

如果您仔细查看该图片,您将看到成员节点具有一大堆我们没有要求的属性。喜欢姓名、地点、性别等。什么给了?嗯,我不想浪费用户的时间问他们的东西,我可以自己解决com/maxdemarzi/neochat/blob/master/网站/src/main/java/com/maxdemarzi/全接触扩展.java”rel=”nofollow”目标=”_blank”=另一个分机,用注册中使用的电子邮件和电话号码调用全联系人API。丰富成员的信息。使用 Neo4j 的一个好事情就是它的架构是可选的。因此,无论我从 FullContact 获得什么属性,我都可以通过此密码查询添加到成员:


String enrichUser = "MATCH (a:Account)-[:HAS_MEMBER]->(member) 
                     WHERE a.id = $id AND member.phone = $phone 
                     SET member += $properties 
                     RETURN member";

但有一些警告。首先,Neo4j 不允许空值,因此我们必须删除这些值。其次,Neo4j 不允许嵌套属性,并且”详细信息”和”数据AddOns”都以 JSON blob 的身份出现,因此它们必须离开。


properties.values().removeIf(Objects::isNull);
properties.remove("details");
properties.remove("dataAddOns");

第三,FullContact API 具有速率限制器(尤其是对于免费计划),因此,它不是在注册时执行请求,而是发送到每秒运行一次后台作业的队列,这样我们就不会超过限制。


{{
    put("email", id);
    put("phone", phone);
}});

现在,我们需要能够使用存储的过程与我们的用户聊天。我们可以调用它,就像从驱动程序的任何 Cypher 查询,传入成员的 ID 和电话以及他们发送给我们的文本:


    String chat = "CALL com.maxdemarzi.chat($id, $phone, $text)";

    static List<Map<String, Object>> Chat(Driver driver, String id, String phone, String text) {
        return Iterators.asList(
            {{
                put("id", id);
                put("phone", phone);
                put("text", text);
            }})
        );
    }

我们将添加一个终结点,以接受他们的聊天帖子请求到使用上述方法的 Jooby 应用程序,并返回对应用程序的响应。


        post("/chat", ctx -> {
            String id = ctx.session().get("id").value();
            String phone = ctx.session().get("phone").value();
            Formdata form = ctx.form();
            String chatText = form.get("chatText").toOptional().orElse("");
            Driver driver = require(Driver.class);
            List<Map<String, Object>> response = CypherQueries.Chat(driver, id, phone, chatText);
            return response;
        });

我们还将这一切与一些老派的Javascript一起连接在一起,因为这就是我记得如何做的,现在为了我们劳动的成果。当我在聊天框中键入”hello”并按 Enter,将调用存储过程,并将新消息附加到我们的会员节点,找出要回复的内容,将其添加到我们的图形中并返回结果。

然后,我们可以在聊天窗口中可视化我们的回复:

…在那里,我们有它。我花了一些努力才达到这个地位。在下一部分中,我们将超越打招呼,并获取一些真正的功能。源代码如既往,在Github上.

进一步阅读

在 Neo4j 中构建聊天机器人(第二部分)

如何从头开始开发聊天机器人

信息和文档聊天机器人

Comments are closed.