Browse Source

迁移到标准库中

louhr 6 years ago
parent
commit
435e92a3a5

+ 20 - 0
nlp-web/src/main/java/org/diagbot/nlp/controller/ParticipleController.java

@@ -1,6 +1,8 @@
 package org.diagbot.nlp.controller;
 
 import org.diagbot.nlp.participle.ParticipleUtil;
+import org.diagbot.nlp.util.DictUtil;
+import org.diagbot.nlp.util.NlpCache;
 import org.diagbot.pub.api.Response;
 import org.diagbot.pub.web.BaseController;
 import org.springframework.stereotype.Controller;
@@ -38,4 +40,22 @@ public class ParticipleController extends BaseController {
         return response;
     }
 
+    @ResponseBody
+    @RequestMapping("/write_file")
+    public Response writeFile() throws IOException {
+        Response response = new Response();
+        long start = System.currentTimeMillis();
+
+        String path = this.getClass().getClassLoader().getResource("").getPath();
+        DictUtil dictUtil = new DictUtil();
+        dictUtil.writeToDict(path);
+
+        NlpCache.createSegmentCache();
+        NlpCache.createSynonymCache();
+        NlpCache.createClassifyCache();
+
+        long end = System.currentTimeMillis();
+        System.out.println("总耗时:........." + (end - start));
+        return response;
+    }
 }

+ 18 - 11
nlp/src/main/java/org/diagbot/nlp/participle/ParticipleToken.java

@@ -37,11 +37,12 @@ public class ParticipleToken {
     private Reader reader;
     //词库二叉树
     private Segment segment;
-
     //词频次
     private float threshold;
     //词性
     private String property;
+    //标准词
+    private String concept;
     //缺省词性
     private String DEFAULT_PROPERTY = "99";
 
@@ -87,7 +88,7 @@ public class ParticipleToken {
             if (cursor - offset <= 1) {
                 this.matchARABIC();
             } else {
-                this.addLexeme(offset, cursor - offset, this.property);
+                this.addLexeme(offset, cursor - offset, this.property, this.concept);
                 this.offset = this.cursor;
             }
         } else if (CharacterUtil.identifyCharType(buffer[cursor]) == CharacterUtil.CHAR_CHINESE_QUANTIFIER) {
@@ -97,7 +98,7 @@ public class ParticipleToken {
             if (cursor - offset <= 1) {
                 this.matchQUANTIFIER();
             } else {
-                this.addLexeme(offset, cursor - offset, this.property);
+                this.addLexeme(offset, cursor - offset, this.property, this.concept);
                 this.offset = this.cursor;
             }
         } else if (CharacterUtil.identifyCharType(buffer[cursor]) == CharacterUtil.CHAR_ENGLISH) {
@@ -108,11 +109,11 @@ public class ParticipleToken {
                 if (this.property == null || ARABIC_PROPERTY.equals(this.property)) {
                     this.matchENGLISH();
                 } else {
-                    this.addLexeme(offset, cursor - offset, this.property);
+                    this.addLexeme(offset, cursor - offset, this.property, this.concept);
                     this.offset = this.cursor;
                 }
             } else {
-                this.addLexeme(offset, cursor - offset, this.property);
+                this.addLexeme(offset, cursor - offset, this.property, this.concept);
                 this.offset = this.cursor;
             }
         }
@@ -129,7 +130,7 @@ public class ParticipleToken {
                 break;
             }
         }
-        this.addLexeme(this.offset, this.cursor - this.offset, "33");
+        this.addLexeme(this.offset, this.cursor - this.offset, "33", "");
         this.offset = this.cursor;
     }
 
@@ -155,7 +156,7 @@ public class ParticipleToken {
                 break;
             }
         }
-        this.addLexeme(this.offset, this.cursor - this.offset, this.ARABIC_PROPERTY);
+        this.addLexeme(this.offset, this.cursor - this.offset, this.ARABIC_PROPERTY, "");
         this.offset = this.cursor;
     }
 
@@ -173,7 +174,7 @@ public class ParticipleToken {
                 break;
             }
         }
-        this.addLexeme(this.offset, this.cursor - this.offset, this.ARABIC_PROPERTY);
+        this.addLexeme(this.offset, this.cursor - this.offset, this.ARABIC_PROPERTY, "");
         this.offset = this.cursor;
     }
 
@@ -223,6 +224,7 @@ public class ParticipleToken {
         //保存词频数据,便于最大长度相同时 按词频排序
         this.threshold = s.getThreshold();
         this.property = s.getProperty();
+        this.concept = s.getConcept();
     }
 
     /**
@@ -242,6 +244,7 @@ public class ParticipleToken {
         int max_begin = o_offset;   //最大长度词默认起始位置为前一个词开始位置
         //词性会被递归覆盖,需要先保存
         String property = this.property;
+        String concept = this.concept;
         while (o_begin < o_cursor - 1) {
             o_begin++;
             this.matchCHN(segment, o_begin, 0, false);      //执行后this.cursor会变化
@@ -249,17 +252,20 @@ public class ParticipleToken {
                 max_length = this.cursor - o_begin;
                 max_begin = o_begin;
                 property = this.property;
+                concept = this.concept;
             } else if (this.cursor - o_begin == max_length) {       //词长度相同 有词性的保留
                 if (this.DEFAULT_PROPERTY.equals(property)
                         && this.property != null && !this.DEFAULT_PROPERTY.equals(this.property)) {
 //                if (this.threshold > o_threshold) {
                     max_begin = o_begin;
                     property = this.property;
+                    concept = this.concept;
                 }
             }
         }
         //还原词性
         this.property = property;
+        this.concept = concept;
         if (max_length >= o_length) {    //如果发现有新词比最初切出来的词更长,那么先对新词前面字符进行切词,this.cursor应该被还原为最初的值,并且只能最多切到新词起始位置
             if (max_begin != o_offset) {
                 this.cursor = this.offset;
@@ -267,7 +273,7 @@ public class ParticipleToken {
                 this.next();
             } else {
                 this.cursor = o_cursor;
-                this.addLexeme(offset, this.cursor - offset, this.property);
+                this.addLexeme(offset, this.cursor - offset, this.property, this.concept);
                 this.offset = this.cursor;
                 this.stop_position = this.text_size;
             }
@@ -275,16 +281,17 @@ public class ParticipleToken {
     }
 
     private void addLexeme(int begin, int length) throws IOException {
-        this.addLexeme(begin, length, this.DEFAULT_PROPERTY);
+        this.addLexeme(begin, length, this.DEFAULT_PROPERTY, "");
     }
 
-    private void addLexeme(int begin, int length, String property) throws IOException {
+    private void addLexeme(int begin, int length, String property, String concept) throws IOException {
         if(length > 0){
             Lexeme lexeme = new Lexeme(begin, length);
             char[] chars = new char[lexeme.getLength()];
             System.arraycopy(buffer, lexeme.getOffset(), chars, 0, lexeme.getLength());
             lexeme.setText(String.valueOf(chars));
             lexeme.setProperty(property==null?this.DEFAULT_PROPERTY:property);
+            lexeme.setConcept(concept);
             lexemePath.add(lexeme);
             //判断是否需要加载文本内容
             this.fillBuffer();

+ 17 - 1
nlp/src/main/java/org/diagbot/nlp/participle/ParticipleUtil.java

@@ -66,7 +66,7 @@ public class ParticipleUtil {
     }
 
     public static String participleAndHighlight(String content) throws IOException {
-        LexemePath<Lexeme> lexemePath = participle(content, true);
+        LexemePath<Lexeme> lexemePath = participle(content, false);
         String separator = "&nbsp;*&nbsp;";
         StringBuffer sb = new StringBuffer();
         Lexeme lexeme = null;
@@ -84,6 +84,9 @@ public class ParticipleUtil {
                     if (lexeme.getProperty() != null && !"99".equals(lexeme.getProperty())) {
                         sb.append("<font color='blue'>");
                         sb.append(lexeme.getText());
+                        if (!StringUtils.isEmpty(lexeme.getConcept()) && hasConcept(lexeme)) {
+                            sb.append("【" + lexeme.getConcept() + "】");
+                        }
                         sb.append("</font>");
                     } else {
                         sb.append(lexeme.getText());
@@ -190,4 +193,17 @@ public class ParticipleUtil {
         }
         return results;
     }
+
+    public static boolean hasConcept(Lexeme lexeme) {
+        if (lexeme.getText().equals(lexeme.getConcept())) {
+            return false;
+        } else {
+            String[] texts = lexeme.getConcept().split(",");
+            boolean hasConcept = true;
+            for (int i = 0; i < texts.length; i++) {
+                hasConcept = lexeme.getText().equals(texts[i]);
+            }
+            return !hasConcept;
+        }
+    }
 }

+ 2 - 3
nlp/src/main/java/org/diagbot/nlp/participle/cfg/DefaultConfig.java

@@ -32,13 +32,12 @@ public class DefaultConfig implements Configuration {
         try {
             String[] line_string;
             char[] chars;
-            EncrypDES encrypDES = new EncrypDES();
             for (i = 0; i < length; i++) {
                 String s = dicts.get(i);
                 line_string = org.apache.commons.lang3.StringUtils.split(dicts.get(i), "\\|");
                 chars = line_string[0].toCharArray();
-                if (line_string.length == 3) {
-                    segment.fill(segment, chars, 0, chars.length, Float.parseFloat(line_string[1]), line_string[2]);
+                if (line_string.length == 4) {
+                    segment.fill(segment, chars, 0, chars.length, Float.parseFloat(line_string[1]), line_string[2], line_string[3]);
                 } else if (line_string.length == 1) {
                     segment.fill(segment, chars, 0, chars.length);
                 } else {

+ 5 - 5
nlp/src/main/java/org/diagbot/nlp/participle/word/Lexeme.java

@@ -14,7 +14,7 @@ public class Lexeme implements Comparable<Lexeme> {
 
     private float threshold;
 
-    private String synonym;
+    private String concept;
 
     public Lexeme(int offset, int length) {
         this.offset = offset;
@@ -66,12 +66,12 @@ public class Lexeme implements Comparable<Lexeme> {
         this.flag = flag;
     }
 
-    public String getSynonym() {
-        return synonym;
+    public String getConcept() {
+        return concept;
     }
 
-    public void setSynonym(String synonym) {
-        this.synonym = synonym;
+    public void setConcept(String concept) {
+        this.concept = concept;
     }
 
     public int compareTo(Lexeme o) {

+ 14 - 3
nlp/src/main/java/org/diagbot/nlp/participle/word/Segment.java

@@ -19,6 +19,8 @@ public class Segment {
     private float threshold = 0f;
     //词性
     private String property;
+    //标准词
+    private String concept;
 
     private Segment parent;
 
@@ -27,10 +29,10 @@ public class Segment {
     }
 
     public void fill(Segment s, char[] chars, int cursor, int length) {
-        this.fill(s, chars, cursor, length, 0f, "99");
+        this.fill(s, chars, cursor, length, 0f, "99", "");
     }
 
-    public void fill(Segment s, char[] chars, int cursor, int length, float threshold, String property) {
+    public void fill(Segment s, char[] chars, int cursor, int length, float threshold, String property, String concept) {
         Character c_char = Character.valueOf(chars[cursor]);
         if (Constants.chn_chars_map.get(c_char) == null) {
             Constants.chn_chars_map.put(c_char, c_char);
@@ -41,11 +43,12 @@ public class Segment {
         if (segment != null) {
             segment.setParent(s);
             if (length > 1) {
-                segment.fill(segment, chars, cursor + 1, length - 1, threshold, property);
+                segment.fill(segment, chars, cursor + 1, length - 1, threshold, property, concept);
             } else {
                 segment.isLexeme = true;
                 segment.threshold = threshold;
                 segment.property = property;
+                segment.concept = concept;
                 segment_map.put(c_char, segment);
             }
         }
@@ -98,4 +101,12 @@ public class Segment {
     public void setProperty(String property) {
         this.property = property;
     }
+
+    public String getConcept() {
+        return concept;
+    }
+
+    public void setConcept(String concept) {
+        this.concept = concept;
+    }
 }

+ 156 - 0
nlp/src/main/java/org/diagbot/nlp/util/DictUtil.java

@@ -0,0 +1,156 @@
+package org.diagbot.nlp.util;
+
+import org.diagbot.pub.jdbc.MysqlJdbc;
+import org.diagbot.pub.utils.security.EncrypDES;
+
+import java.io.FileWriter;
+import java.io.IOException;
+import java.sql.Connection;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.sql.Statement;
+import java.util.*;
+
+/**
+ * @ClassName org.diagbot.nlp.test.LexemeDicFromMed
+ * @Description TODO
+ * @Author fyeman
+ * @Date 2019/4/10/010 13:32
+ * @Version 1.0
+ **/
+public class DictUtil {
+    public static void main(String[] args) {
+        DictUtil test = new DictUtil();
+
+        String path = test.getClass().getClassLoader().getResource("").getPath();
+        path = path.substring(0, path.indexOf("target")) + "src/main/resources/";
+
+        test.writeToDict(path);
+    }
+
+    public void writeToDict(String path) {
+        MysqlJdbc nlpJdbc = new MysqlJdbc("root", "diagbot@20180822", "jdbc:mysql://192.168.2.235:3306/diagbot-med?useUnicode=true&characterEncoding=UTF-8");
+        Connection conn = nlpJdbc.connect();
+        Statement st = null;
+        ResultSet rs = null;
+        try {
+            EncrypDES encrypDES = new EncrypDES();
+            //所有词典库 不能用concat_group 大小写不区分
+            String sql = "select l_1.name l_1_name, l_1.type_id type_id, l_2.name l_2_name from library_info l_1 " +
+                    "left join library_info l_2 on l_1.concept_id = l_2.concept_id and l_2.is_concept = 1 ";
+            st = conn.createStatement();
+            rs = st.executeQuery(sql);
+            FileWriter fw = new FileWriter(path + "tc.dict");
+
+            Map<String, String> idMap = new HashMap<>(10);
+            Map<String, String> nameMap = new HashMap<>(10);
+            String r1;
+            String r2;
+            String r3;
+            while (rs.next()) {
+                r1 = rs.getString(1);
+                r2 = rs.getString(2);
+                r3 = rs.getString(3);
+                if (idMap.get(r1) == null) {
+                    idMap.put(r1, r2);
+                    nameMap.put(r1, r3);
+                } else if (idMap.get(r1) != null) {
+                    idMap.put(r1, idMap.get(r1) + "," + r2);
+                    nameMap.put(r1, nameMap.get(r1) + "," + r3);
+                }
+            }
+
+            List<Map.Entry<String, String>> libraryList = new ArrayList<Map.Entry<String, String>>(idMap.entrySet());
+            Collections.sort(libraryList, new Comparator<Map.Entry<String, String>>() {
+                public int compare(Map.Entry<String, String> o1, Map.Entry<String, String> o2) {
+                    return o1.getKey().compareTo(o2.getKey());
+                }
+            });
+            for (Map.Entry<String, String> entry : libraryList) {
+                fw.write(encrypDES.encrytor(entry.getKey() + "|9|"
+                        + entry.getValue() + "|" + nameMap.get(entry.getKey())));
+                fw.write("\n");
+            }
+
+            fw.close();
+
+            sql = "SELECT l_1.name l_1_name, l_2.name l_2_name FROM library_info l_1 " +
+                    "left join library_info l_2 on l_1.concept_id = l_2.concept_id and l_2.is_concept = '1' " +
+                    "where l_1.is_concept = '0'";
+            st = conn.createStatement();
+            rs = st.executeQuery(sql);
+
+            libraryList = rsToMap(rs, false);
+
+            fw = new FileWriter(path + "synonym.dict");
+            for (Map.Entry<String, String> entry : libraryList) {
+                fw.write(encrypDES.encrytor(entry.getKey() + "|" + entry.getValue()));
+                fw.write("\n");
+            }
+            fw.close();
+
+            sql = "SELECT l_1.name l_1_name, l_2.name l_2_name FROM relation r " +
+                    "left join concept c1 on r.start_id = c1.id " +
+                    "left join concept c2 on r.end_id = c2.id " +
+                    "left join library_info l_1 on l_1.id = c1.lib_id " +
+                    "left join library_info l_2 on l_2.id = c2.lib_id";
+            st = conn.createStatement();
+            rs = st.executeQuery(sql);
+
+            libraryList = rsToMap(rs, false);
+
+            fw = new FileWriter(path + "classify.dict");
+            for (Map.Entry<String, String> entry : libraryList) {
+                fw.write(encrypDES.encrytor(entry.getKey() + "|" + entry.getValue()));
+                fw.write("\n");
+            }
+            fw.close();
+
+            //推送词典
+            sql = "select l.name, l.type_id from bg_library_prop bp, library_info l " +
+                    "where bp.concept_id = l.concept_id  and l.is_concept = 1 and type_id != 99 and bp.is_push = 1 order by l.name";
+            st = conn.createStatement();
+            rs = st.executeQuery(sql);
+            libraryList = rsToMap(rs, true);
+
+            fw = new FileWriter(path + "push-tc.dict");
+            for (Map.Entry<String, String> entry : libraryList) {
+                fw.write(encrypDES.encrytor(entry.getKey() + "|" + entry.getValue()));
+                fw.write("\n");
+            }
+            fw.close();
+        } catch (IOException ioe) {
+            ioe.printStackTrace();
+        } catch (SQLException sqle) {
+            sqle.printStackTrace();
+        } catch (Exception e) {
+            e.printStackTrace();
+        } finally {
+            nlpJdbc.close(rs, st, conn);
+        }
+    }
+
+    private List<Map.Entry<String, String>> rsToMap(ResultSet rs, boolean isJoin) throws SQLException{
+        String r1 = "";
+        String r2 = "";
+        Map<String, String> libraryMap = new HashMap<>(10);
+        while (rs.next()) {
+            r1 = rs.getString(1);
+            r2 = rs.getString(2);
+            if (libraryMap.get(r1) == null) {
+                libraryMap.put(r1, r2);
+            } else if (isJoin && libraryMap.get(r1) != null) {
+                libraryMap.put(r1, libraryMap.get(r1) + "," + r2);
+            }
+        }
+
+        List<Map.Entry<String, String>> libraryList = new ArrayList<Map.Entry<String, String>>(libraryMap.entrySet());
+        Collections.sort(libraryList, new Comparator<Map.Entry<String, String>>() {
+            public int compare(Map.Entry<String, String> o1, Map.Entry<String, String> o2) {
+                return o1.getKey().compareTo(o2.getKey());
+            }
+        });
+
+        return libraryList;
+    }
+}

File diff suppressed because it is too large
+ 4266 - 3216
nlp/src/main/resources/classify.dict


File diff suppressed because it is too large
+ 211 - 2188
nlp/src/main/resources/push-tc.dict


File diff suppressed because it is too large
+ 6694 - 9076
nlp/src/main/resources/synonym.dict


File diff suppressed because it is too large
+ 351636 - 351680
nlp/src/main/resources/tc.dict


+ 0 - 22
pom.xml

@@ -185,13 +185,6 @@
         <!-- AOP end -->
 
         <!-- LOGGING begin -->
-        <!-- slf4j -->
-        <dependency>
-            <groupId>ch.qos.logback</groupId>
-            <artifactId>logback-classic</artifactId>
-            <version>${logback.version}</version>
-        </dependency>
-
         <!-- 代码直接调用commons-logging会被桥接到slf4j -->
         <dependency>
             <groupId>org.slf4j</groupId>
@@ -206,15 +199,6 @@
             <version>${slf4j.version}</version>
         </dependency>
 
-        <!-- log4jdbc -->
-        <dependency>
-            <groupId>com.googlecode.log4jdbc</groupId>
-            <artifactId>log4jdbc</artifactId>
-            <version>1.2</version>
-            <scope>runtime</scope>
-        </dependency>
-        <!-- LOGGING end -->
-
         <dependency>
             <groupId>org.apache.httpcomponents</groupId>
             <artifactId>httpclient</artifactId>
@@ -268,12 +252,6 @@
             <artifactId>fastjson</artifactId>
             <version>1.2.46</version>
         </dependency>
-
-        <dependency>
-            <groupId>log4j</groupId>
-            <artifactId>log4j</artifactId>
-            <version>1.2.17</version>
-        </dependency>
     </dependencies>
 
     <!-- .properties xml进行打包 -->

+ 6 - 0
push-web/pom.xml

@@ -76,6 +76,12 @@
 		<artifactId>mybatis-spring-boot-starter</artifactId>
 		<version>1.3.2</version>
 		</dependency>
+
+		<dependency>
+			<groupId>org.springframework.boot</groupId>
+			<artifactId>spring-boot-starter-logging</artifactId>
+		</dependency>
+
 		<!-- 分页插件 -->
 		<dependency>
 		<groupId>com.github.pagehelper</groupId>

+ 0 - 5
push-web/src/main/resources/push.properties

@@ -1,5 +0,0 @@
-bigdata.http.url=http://192.168.2.234:5001/bigdata-web/algorithm/neural
-graph.http.url=http://192.168.2.234:5003/graph-web/graph/push
-
-#bigdata.http.url=http://192.168.3.180:5001/bigdata-web/algorithm/neural
-#graph.http.url=http://192.168.3.180:5003/graph-web/graph/push

+ 70 - 1
push-web/src/main/resources/static/index.html

@@ -126,6 +126,9 @@
             <button type="button" class="btn btn-success pull-right" onclick="_ajax('/participle/split_and_highlight')"><i
                     class="fa fa-credit-card"></i> 开&nbsp;始&nbsp;分&nbsp;析
             </button>
+            <button type="button" class="btn btn-success pull-right" onclick="writeFile('/participle/write_file')"><i
+                    class="fa fa-credit-card"></i> 加&nbsp;载&nbsp;词&nbsp;库
+            </button>
           </div>
         </div>
       </div>
@@ -142,6 +145,31 @@
                   }
               });
           };
+
+
+          function writeFile(url) {
+              $.support.cors = true;
+
+              $("#modal-loading").show();
+              $("#modal-default .modal-header").hide();
+              $("#modal-default .modal-body p").text("");
+              $("#modal-default .modal-footer").hide();
+              $("#modal-default").modal("show");
+
+              $.ajax({
+                  url: nlp_web_url + url,
+                  data: $("#participle_form").serialize(),
+                  dataType: "json",
+                  type: "post",
+                  success: function (data) {
+                      $("#modal-loading").hide();
+                      $("#modal-default .modal-header").show();
+                      $("#modal-default .modal-footer").show();
+                      $("#modal-default .modal-body p").text(data.msg);
+                      $("#modal-default").modal("show");
+                  }
+              });
+          };
       </script>
       <div class="row invoice-info">
         <div class="col-sm-12 invoice-col" id = "participle_result">
@@ -158,7 +186,48 @@
   <div class="control-sidebar-bg"></div>
 </div>
 <!-- ./wrapper -->
-
+<div class="modal fade" id="modal-default">
+  <div class="modal-dialog">
+    <div class="modal-content">
+      <div class="modal-header">
+        <button type="button" class="close" data-dismiss="modal" aria-label="Close">
+          <span aria-hidden="true">&times;</span></button>
+        <h4 class="modal-title">消息</h4>
+      </div>
+      <div class="row" id="modal-loading">
+        <!-- /.col -->
+        <div class="col-md-12">
+          <div class="box box-danger box-solid">
+            <div class="box-header">
+              <h3 class="box-title">重新生成词库</h3>
+            </div>
+            <div class="box-body">
+              此过程可能需要较长时间,请耐心等待... ...
+            </div>
+            <!-- /.box-body -->
+            <!-- Loading (remove the following to stop the loading)-->
+            <div class="overlay">
+              <i class="fa fa-refresh fa-spin"></i>
+            </div>
+            <!-- end loading -->
+          </div>
+          <!-- /.box -->
+        </div>
+        <!-- /.col -->
+      </div>
+      <!-- /.row -->
+      <div class="modal-body">
+        <p></p>
+      </div>
+      <div class="modal-footer">
+        <button type="button" class="btn btn-default pull-left" data-dismiss="modal">Close</button>
+      </div>
+    </div>
+    <!-- /.modal-content -->
+  </div>
+  <!-- /.modal-dialog -->
+</div>
+<!-- /.modal -->
 <!-- Bootstrap 3.3.6 -->
 <script src="bootstrap/js/bootstrap.min.js"></script>
 <!-- FastClick -->

+ 69 - 3
push-web/src/main/resources/static/pages/participle/sample.html

@@ -122,9 +122,9 @@
             <button type="button" class="btn btn-success pull-right" onclick="_ajax('/participle/split_and_highlight')"><i
                     class="fa fa-credit-card"></i> 开&nbsp;始&nbsp;分&nbsp;析
             </button>
-            <!--<button type="button" class="btn btn-success pull-right" onclick="_ajax('/web/participle/write_file')"><i-->
-                    <!--class="fa fa-credit-card"></i> 生&nbsp;成&nbsp;文&nbsp;件-->
-            <!--</button>-->
+            <button type="button" class="btn btn-success pull-right" onclick="writeFile('/participle/write_file')"><i
+                    class="fa fa-credit-card"></i> 加&nbsp;载&nbsp;词&nbsp;库
+            </button>
           </div>
         </div>
       </div>
@@ -141,6 +141,30 @@
                   }
               });
           };
+
+          function writeFile(url) {
+              $.support.cors = true;
+
+              $("#modal-loading").show();
+              $("#modal-default .modal-header").hide();
+              $("#modal-default .modal-body p").text("");
+              $("#modal-default .modal-footer").hide();
+              $("#modal-default").modal("show");
+
+              $.ajax({
+                  url: nlp_web_url + url,
+                  data: $("#participle_form").serialize(),
+                  dataType: "json",
+                  type: "post",
+                  success: function (data) {
+                      $("#modal-loading").hide();
+                      $("#modal-default .modal-header").show();
+                      $("#modal-default .modal-footer").show();
+                      $("#modal-default .modal-body p").text(data.msg);
+                      $("#modal-default").modal("show");
+                  }
+              });
+          };
       </script>
       <div class="row invoice-info">
         <div class="col-sm-12 invoice-col" id = "participle_result">
@@ -157,6 +181,48 @@
   <div class="control-sidebar-bg"></div>
 </div>
 <!-- ./wrapper -->
+<div class="modal fade" id="modal-default">
+  <div class="modal-dialog">
+    <div class="modal-content">
+      <div class="modal-header">
+        <button type="button" class="close" data-dismiss="modal" aria-label="Close">
+          <span aria-hidden="true">&times;</span></button>
+        <h4 class="modal-title">消息</h4>
+      </div>
+      <div class="row" id="modal-loading">
+        <!-- /.col -->
+        <div class="col-md-12">
+          <div class="box box-danger box-solid">
+            <div class="box-header">
+              <h3 class="box-title">重新生成词库</h3>
+            </div>
+            <div class="box-body">
+              此过程可能需要较长时间,请耐心等待... ...
+            </div>
+            <!-- /.box-body -->
+            <!-- Loading (remove the following to stop the loading)-->
+            <div class="overlay">
+              <i class="fa fa-refresh fa-spin"></i>
+            </div>
+            <!-- end loading -->
+          </div>
+          <!-- /.box -->
+        </div>
+        <!-- /.col -->
+      </div>
+      <!-- /.row -->
+      <div class="modal-body">
+        <p></p>
+      </div>
+      <div class="modal-footer">
+        <button type="button" class="btn btn-default pull-left" data-dismiss="modal">Close</button>
+      </div>
+    </div>
+    <!-- /.modal-content -->
+  </div>
+  <!-- /.modal-dialog -->
+</div>
+<!-- /.modal -->
 
 <!-- jQuery 2.2.3 -->
 <script src="../plugins/jQuery/jquery-2.2.3.min.js"></script>