diff --git a/cc-chatbot/README.md b/cc-chatbot/README.md
index 366035b4..d0185eda 100644
--- a/cc-chatbot/README.md
+++ b/cc-chatbot/README.md
@@ -10,4 +10,64 @@ https://docs.chatopera.com/
* 查询聊天机器人使用情况
* 管理和检索多轮对话
* 管理和检索知识库
-* 检索意图识别
\ No newline at end of file
+* 检索意图识别
+
+
+# 配置
+
+使用maven,需要配置Chatopera的Nexus OSS仓库,具体见[文档](https://github.com/chatopera/cosin/wiki/%E6%98%A5%E6%9D%BE%E5%AE%A2%E6%9C%8D%EF%BC%9A%E5%BC%80%E5%8F%91%E7%8E%AF%E5%A2%83#%E4%BF%AE%E6%94%B9maven2%E9%85%8D%E7%BD%AE)。
+
+```
+
+ com.chatopera.chatbot
+ sdk
+ 1.0-SNAPSHOT
+
+```
+
+# API
+
+## Chatbot v1
+
+聊天机器人类,构造参数(tcp协议,hostname, 端口, 版本)
+
+### Chatbot#getChatbots
+获取聊天机器人列表,支持检索查询,分页
+
+### Chatbot#getChatbot
+通过聊天机器人ID获得聊天机器人详情
+
+### Chatbot#conversation
+与指定的聊天机器人进行多轮对话
+
+### Chatbot#faq
+与指定的聊天机器人进行知识库问答
+
+
+# 测试
+
+```
+mvn test
+```
+
+# 示例
+
+```
+Chatbot cb = new Chatbot("http", "lhc-dev", 8003, "v1");
+JSONObject resp = cb.conversation("co_bot_1", "sdktest", "华夏春松在哪里", false);
+```
+
+返回值参考 [智能问答引擎文档](https://docs.chatopera.com/chatbot-engine.html)。
+
+
+## 开源许可协议
+
+Copyright (2018) 北京华夏春松科技有限公司
+
+[Apache License Version 2.0](https://github.com/chatopera/cosin/blob/master/LICENSE)
+
+[![chatoper banner][co-banner-image]][co-url]
+
+[co-banner-image]: https://user-images.githubusercontent.com/3538629/42383104-da925942-8168-11e8-8195-868d5fcec170.png
+[co-url]: https://www.chatopera.com
+
diff --git a/cc-chatbot/admin/test.sh b/cc-chatbot/admin/test.sh
new file mode 100755
index 00000000..d122e6a0
--- /dev/null
+++ b/cc-chatbot/admin/test.sh
@@ -0,0 +1,13 @@
+#! /bin/bash
+###########################################
+#
+###########################################
+
+# constants
+baseDir=$(cd `dirname "$0"`;pwd)
+# functions
+
+# main
+[ -z "${BASH_SOURCE[0]}" -o "${BASH_SOURCE[0]}" = "$0" ] || return
+cd $baseDir/../app
+mvn test
diff --git a/cc-chatbot/app/pom.xml b/cc-chatbot/app/pom.xml
index 57ad6936..9b2c6a0b 100644
--- a/cc-chatbot/app/pom.xml
+++ b/cc-chatbot/app/pom.xml
@@ -20,6 +20,16 @@
+
+ org.slf4j
+ slf4j-api
+ 1.7.25
+
+
+ org.slf4j
+ slf4j-simple
+ 1.7.25
+
org.apache.commons
commons-lang3
@@ -41,9 +51,9 @@
4.3.6
- com.google.code.gson
- gson
- 2.8.1
+ org.json
+ json
+ 20140107
com.mashape.unirest
@@ -55,6 +65,12 @@
junit
3.8.1
+
+ junit
+ junit
+ 4.12
+ test
+
diff --git a/cc-chatbot/app/src/main/java/com/chatopera/chatbot/App.java b/cc-chatbot/app/src/main/java/com/chatopera/chatbot/App.java
deleted file mode 100644
index 26eb6163..00000000
--- a/cc-chatbot/app/src/main/java/com/chatopera/chatbot/App.java
+++ /dev/null
@@ -1,13 +0,0 @@
-package com.chatopera.chatbot;
-
-/**
- * Hello world!
- *
- */
-public class App
-{
- public static void main( String[] args )
- {
- System.out.println( "Hello World!" );
- }
-}
diff --git a/cc-chatbot/app/src/main/java/com/chatopera/chatbot/Chatbot.java b/cc-chatbot/app/src/main/java/com/chatopera/chatbot/Chatbot.java
new file mode 100644
index 00000000..28bdae01
--- /dev/null
+++ b/cc-chatbot/app/src/main/java/com/chatopera/chatbot/Chatbot.java
@@ -0,0 +1,159 @@
+package com.chatopera.chatbot;
+
+import com.mashape.unirest.http.exceptions.UnirestException;
+import org.apache.commons.lang3.StringUtils;
+import org.json.JSONObject;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.HashMap;
+
+public class Chatbot {
+ private static final Logger logger = LoggerFactory.getLogger(Chatbot.class);
+ private String schema;
+ private String hostname;
+ private int port;
+ private String baseUrl;
+
+ private Chatbot() {
+ }
+
+ public Chatbot(final String schema, final String hostname, final int port, final String version) {
+ this.schema = schema;
+ this.hostname = hostname;
+ this.port = port;
+ this.baseUrl = schema + "://" + hostname + ":" + Integer.toString(this.port) + "/api/" + version;
+ }
+
+ public Chatbot(final String schema, final String hostname, final int port) {
+ this(schema, hostname, port, "v1");
+ }
+
+ public Chatbot(final String hostname, final int port) {
+ this("http", hostname, port);
+ }
+
+ public String getSchema() {
+ return schema;
+ }
+
+ public String getHostname() {
+ return hostname;
+ }
+
+ public int getPort() {
+ return port;
+ }
+
+ public String getBaseUrl() {
+ return baseUrl;
+ }
+
+ /**
+ * 获取聊天机器人列表
+ *
+ * @return
+ * @throws ChatbotRuntimeException
+ */
+ public JSONObject getChatbots(final String fields, final String q, final int page, final int limit) throws ChatbotRuntimeException {
+ try {
+ HashMap queryString = new HashMap();
+ if (StringUtils.isNotBlank(fields)) {
+ queryString.put("fields", fields);
+ }
+
+ if (StringUtils.isNotBlank(q)) {
+ queryString.put("q", q);
+ }
+
+ queryString.put("page", page);
+
+ if (limit > 0) {
+ queryString.put("limit", limit);
+ }
+
+ return RestAPI.get(this.getBaseUrl() + "/chatbot", queryString);
+ } catch (UnirestException e) {
+ throw new ChatbotRuntimeException(e.toString());
+ }
+ }
+
+ /**
+ * 获取聊天机器人详情
+ *
+ * @param chatbotID
+ * @return
+ * @throws ChatbotRuntimeException
+ */
+ public JSONObject getChatbot(final String chatbotID) throws ChatbotRuntimeException {
+ try {
+ return RestAPI.get(this.getBaseUrl() + "/chatbot/" + chatbotID);
+ } catch (UnirestException e) {
+ throw new ChatbotRuntimeException(e.toString());
+ }
+ }
+
+ /**
+ * validate params
+ * @param chatbotID
+ * @param fromUserId
+ * @param textMessage
+ */
+ private void v(final String chatbotID, final String fromUserId, final String textMessage) throws ChatbotRuntimeException {
+ if(StringUtils.isBlank(chatbotID))
+ throw new ChatbotRuntimeException("[conversation] 不合法的聊天机器人标识。");
+
+ if(StringUtils.isBlank(fromUserId))
+ throw new ChatbotRuntimeException("[conversation] 不合法的用户标识。");
+
+ if(StringUtils.isBlank(textMessage))
+ throw new ChatbotRuntimeException("[conversation] 不合法的消息内容。");
+ }
+
+ /**
+ * 与聊天机器人进行多轮对话
+ * @param fromUserId
+ * @param textMessage
+ * @param debug
+ * @return
+ */
+ public JSONObject conversation(final String chatbotID, final String fromUserId, final String textMessage, boolean debug) throws ChatbotRuntimeException {
+ v(chatbotID, fromUserId, textMessage);
+ HashMap body = new HashMap();
+ body.put("fromUserId", fromUserId);
+ body.put("textMessage", textMessage);
+ body.put("isDebug", debug);
+
+ logger.info("conversation body {}", body);
+
+ try {
+ JSONObject resp = RestAPI.post(this.getBaseUrl() + "/chatbot/" + chatbotID + "/conversation/query", body);
+ return resp;
+ } catch (UnirestException e) {
+ throw new ChatbotRuntimeException(e.toString());
+ }
+ }
+
+ /**
+ * 检索知识库
+ * @param chatbotID
+ * @param fromUserId
+ * @param textMessage
+ * @param isDebug
+ * @return
+ */
+ public JSONObject faq(final String chatbotID, final String fromUserId, final String textMessage, final boolean isDebug) throws ChatbotRuntimeException {
+ v(chatbotID, fromUserId, textMessage);
+ HashMap body = new HashMap();
+ body.put("fromUserId", fromUserId);
+ body.put("query", textMessage);
+ body.put("isDebug", isDebug);
+ try {
+ JSONObject resp = RestAPI.post(this.getBaseUrl() + "/chatbot/" + chatbotID + "/faq/query", body);
+ return resp;
+ } catch (UnirestException e) {
+ throw new ChatbotRuntimeException(e.toString());
+ }
+ }
+
+}
diff --git a/cc-chatbot/app/src/main/java/com/chatopera/chatbot/ChatbotRuntimeException.java b/cc-chatbot/app/src/main/java/com/chatopera/chatbot/ChatbotRuntimeException.java
new file mode 100644
index 00000000..76fe8c3f
--- /dev/null
+++ b/cc-chatbot/app/src/main/java/com/chatopera/chatbot/ChatbotRuntimeException.java
@@ -0,0 +1,9 @@
+package com.chatopera.chatbot;
+
+import com.mashape.unirest.http.exceptions.UnirestException;
+
+public class ChatbotRuntimeException extends Exception{
+ public ChatbotRuntimeException(String msg) {
+ super(msg);
+ }
+}
diff --git a/cc-chatbot/app/src/main/java/com/chatopera/chatbot/RestAPI.java b/cc-chatbot/app/src/main/java/com/chatopera/chatbot/RestAPI.java
new file mode 100644
index 00000000..3ae36563
--- /dev/null
+++ b/cc-chatbot/app/src/main/java/com/chatopera/chatbot/RestAPI.java
@@ -0,0 +1,99 @@
+package com.chatopera.chatbot;
+
+import com.mashape.unirest.http.HttpResponse;
+import com.mashape.unirest.http.JsonNode;
+import com.mashape.unirest.http.Unirest;
+import com.mashape.unirest.http.exceptions.UnirestException;
+import com.mashape.unirest.request.GetRequest;
+import com.mashape.unirest.request.HttpRequestWithBody;
+import org.json.JSONObject;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.HashMap;
+
+/**
+ * RestAPI接口
+ */
+public class RestAPI {
+ private static final Logger logger = LoggerFactory.getLogger(RestAPI.class);
+
+ /**
+ * patch headers
+ *
+ * @param headers
+ */
+ private static void x(HashMap headers) {
+ if (headers == null) {
+ headers = new HashMap();
+ headers.put("accept", "application/json");
+ return;
+ }
+
+ if (!headers.containsKey("Content-Type"))
+ headers.put("Content-Type", "application/json");
+
+
+ if (!headers.containsKey("accept"))
+ headers.put("accept", "application/json");
+ }
+
+
+ /**
+ * Post
+ *
+ * @param url
+ * @param body
+ * @param query
+ * @param headers
+ * @return
+ * @throws UnirestException
+ */
+ public static JSONObject post(final String url, final HashMap body, final HashMap query, HashMap headers) throws UnirestException {
+ HttpRequestWithBody request = Unirest.post(url);
+ logger.info("post body {}", body.toString());
+ x(headers);
+ HttpResponse resp = request
+ .headers(headers)
+ .queryString(query)
+ .fields(body)
+ .asJson();
+
+ // parse response
+ JSONObject obj = resp.getBody().getObject();
+ return obj;
+ }
+
+ public static JSONObject post(final String url, final HashMap body) throws UnirestException {
+ return post(url, body, null, null);
+ }
+
+ /**
+ * Get
+ *
+ * @param url
+ * @param queryString
+ * @param headers
+ * @return
+ * @throws UnirestException
+ */
+ public static JSONObject get(final String url, final HashMap queryString, HashMap headers) throws UnirestException {
+ GetRequest request = Unirest.get(url);
+ x(headers);
+ HttpResponse resp = request
+ .headers(headers)
+ .queryString(queryString)
+ .asJson();
+ // parse response
+ JSONObject obj = resp.getBody().getObject();
+ return obj;
+ }
+
+ public static JSONObject get(final String url) throws UnirestException {
+ return get(url, null, null);
+ }
+
+ public static JSONObject get(final String url, HashMap queryString) throws UnirestException {
+ return get(url, queryString, null);
+ }
+}
diff --git a/cc-chatbot/app/src/test/java/com/chatopera/chatbot/AppTest.java b/cc-chatbot/app/src/test/java/com/chatopera/chatbot/AppTest.java
deleted file mode 100644
index 65480485..00000000
--- a/cc-chatbot/app/src/test/java/com/chatopera/chatbot/AppTest.java
+++ /dev/null
@@ -1,38 +0,0 @@
-package com.chatopera.chatbot;
-
-import junit.framework.Test;
-import junit.framework.TestCase;
-import junit.framework.TestSuite;
-
-/**
- * Unit test for simple App.
- */
-public class AppTest
- extends TestCase
-{
- /**
- * Create the test case
- *
- * @param testName name of the test case
- */
- public AppTest( String testName )
- {
- super( testName );
- }
-
- /**
- * @return the suite of tests being tested
- */
- public static Test suite()
- {
- return new TestSuite( AppTest.class );
- }
-
- /**
- * Rigourous Test :-)
- */
- public void testApp()
- {
- assertTrue( true );
- }
-}
diff --git a/cc-chatbot/app/src/test/java/com/chatopera/chatbot/ChatbotTest.java b/cc-chatbot/app/src/test/java/com/chatopera/chatbot/ChatbotTest.java
new file mode 100644
index 00000000..90197a54
--- /dev/null
+++ b/cc-chatbot/app/src/test/java/com/chatopera/chatbot/ChatbotTest.java
@@ -0,0 +1,81 @@
+package com.chatopera.chatbot;
+
+import junit.framework.Test;
+import junit.framework.TestCase;
+import junit.framework.TestSuite;
+import org.json.JSONObject;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Unit test for simple App.
+ */
+public class ChatbotTest
+ extends TestCase {
+ private static final Logger logger = LoggerFactory.getLogger(ChatbotTest.class);
+ private Chatbot cb;
+
+ /**
+ * Create the test case
+ *
+ * @param testName name of the test case
+ */
+ public ChatbotTest(String testName) {
+ super(testName);
+ }
+
+ /**
+ * @return the suite of tests being tested
+ */
+ public static Test suite() {
+ return new TestSuite(ChatbotTest.class);
+ }
+
+ public void setUp() {
+ this.cb = new Chatbot("http", "lhc-dev", 8003, "v1");
+ }
+
+ /**
+ * Rigourous Test :-)
+ */
+ public void testChatbot() {
+ assertEquals(this.cb.getPort(), 8003);
+ }
+
+ public void testGetChatbot() {
+ try {
+ JSONObject resp = this.cb.getChatbot("co_bot_1");
+ logger.info("[testGetChatbot] {}", resp.toString());
+ } catch (ChatbotRuntimeException e) {
+ e.printStackTrace();
+ }
+ }
+
+ public void testGetChatbots() {
+ try {
+ JSONObject resp = this.cb.getChatbots("name chatbotID", null, 0, 10);
+ logger.info("[testGetChatbots] resp {}", resp.toString());
+ } catch (ChatbotRuntimeException e) {
+ e.printStackTrace();
+ }
+ }
+
+ public void testConversation(){
+ try {
+ JSONObject resp = this.cb.conversation("co_bot_1", "sdktest", "华夏春松在哪里", false);
+ logger.info("[testConversation] resp {}", resp.toString());
+ } catch (ChatbotRuntimeException e) {
+ e.printStackTrace();
+ }
+ }
+
+ public void testFaq(){
+ try {
+ JSONObject resp = this.cb.faq("co_bot_1", "sdktest", "华夏春松在哪里", false);
+ logger.info("[testFaq] resp {}", resp.toString());
+ } catch (ChatbotRuntimeException e) {
+ e.printStackTrace();
+ }
+ }
+
+}