From 94a35f369b1a1ab22afc14d0a572fe346997483d Mon Sep 17 00:00:00 2001 From: zhoushunjie Date: Mon, 15 Aug 2022 22:32:11 +0800 Subject: [PATCH 01/17] implement PredictUIEInput --- .../ernie/cpp/CMakeLists.txt | 2 +- .../information_extraction/ernie/cpp/infer.cc | 165 +--------- .../information_extraction/ernie/cpp/uie.cc | 287 ++++++++++++++++++ .../information_extraction/ernie/cpp/uie.h | 102 +++++++ 4 files changed, 399 insertions(+), 157 deletions(-) create mode 100644 examples/text/information_extraction/ernie/cpp/uie.cc create mode 100644 examples/text/information_extraction/ernie/cpp/uie.h diff --git a/examples/text/information_extraction/ernie/cpp/CMakeLists.txt b/examples/text/information_extraction/ernie/cpp/CMakeLists.txt index 1189820cb79..6d6faad76c2 100644 --- a/examples/text/information_extraction/ernie/cpp/CMakeLists.txt +++ b/examples/text/information_extraction/ernie/cpp/CMakeLists.txt @@ -21,5 +21,5 @@ include(${FASTDEPLOY_INSTALL_DIR}/FastDeploy.cmake) include_directories(${FASTDEPLOY_INCS}) -add_executable(infer_ernie_demo ${PROJECT_SOURCE_DIR}/infer.cc) +add_executable(infer_ernie_demo ${PROJECT_SOURCE_DIR}/infer.cc ${PROJECT_SOURCE_DIR}/uie.cc) target_link_libraries(infer_ernie_demo ${FASTDEPLOY_LIBS}) diff --git a/examples/text/information_extraction/ernie/cpp/infer.cc b/examples/text/information_extraction/ernie/cpp/infer.cc index 7f3b9318664..ce9313a0048 100644 --- a/examples/text/information_extraction/ernie/cpp/infer.cc +++ b/examples/text/information_extraction/ernie/cpp/infer.cc @@ -18,165 +18,18 @@ #include "fastdeploy/function/softmax.h" #include "fastdeploy/text.h" #include "tokenizers/ernie_faster_tokenizer.h" +#include "uie.h" using namespace paddlenlp; -void LoadTransitionFromFile(const std::string& file, - std::vector* transitions, int* num_tags) { - std::ifstream fin(file); - std::string curr_transition; - float transition; - int i = 0; - while (fin) { - std::getline(fin, curr_transition); - std::istringstream iss(curr_transition); - while (iss) { - iss >> transition; - transitions->push_back(transition); - } - if (curr_transition != "") { - ++i; - } - } - *num_tags = i; -} - -template -void ViterbiDecode(const fastdeploy::FDTensor& slot_logits, - const fastdeploy::FDTensor& trans, - fastdeploy::FDTensor* best_path) { - int batch_size = slot_logits.shape[0]; - int seq_len = slot_logits.shape[1]; - int num_tags = slot_logits.shape[2]; - best_path->Allocate({batch_size, seq_len}, fastdeploy::FDDataType::INT64); - - const T* slot_logits_ptr = reinterpret_cast(slot_logits.Data()); - const T* trans_ptr = reinterpret_cast(trans.Data()); - int64_t* best_path_ptr = reinterpret_cast(best_path->Data()); - std::vector scores(num_tags); - std::copy(slot_logits_ptr, slot_logits_ptr + num_tags, scores.begin()); - std::vector> M(num_tags, std::vector(num_tags)); - for (int b = 0; b < batch_size; ++b) { - std::vector> paths; - const T* curr_slot_logits_ptr = slot_logits_ptr + b * seq_len * num_tags; - int64_t* curr_best_path_ptr = best_path_ptr + b * seq_len; - for (int t = 1; t < seq_len; t++) { - for (size_t i = 0; i < num_tags; i++) { - for (size_t j = 0; j < num_tags; j++) { - auto trans_idx = i * num_tags * num_tags + j * num_tags; - auto slot_logit_idx = t * num_tags + j; - M[i][j] = scores[i] + trans_ptr[trans_idx] + - curr_slot_logits_ptr[slot_logit_idx]; - } - } - std::vector idxs; - for (size_t i = 0; i < num_tags; i++) { - T max = 0.0f; - int idx = 0; - for (size_t j = 0; j < num_tags; j++) { - if (M[j][i] > max) { - max = M[j][i]; - idx = j; - } - } - scores[i] = max; - idxs.push_back(idx); - } - paths.push_back(idxs); - } - int scores_max_index = 0; - float scores_max = 0.0f; - for (size_t i = 0; i < scores.size(); i++) { - if (scores[i] > scores_max) { - scores_max = scores[i]; - scores_max_index = i; - } - } - curr_best_path_ptr[seq_len - 1] = scores_max_index; - for (int i = seq_len - 2; i >= 0; i--) { - int index = curr_best_path_ptr[i + 1]; - curr_best_path_ptr[i] = paths[i][index]; - } - } -} - int main() { - // 1. Define a ernie faster tokenizer - faster_tokenizer::tokenizers_impl::ErnieFasterTokenizer tokenizer( - "ernie_vocab.txt"); - std::vector strings_list = { - "导航去科技园二号楼", "屏幕亮度为我减小一点吧"}; - std::vector encodings; - tokenizer.EncodeBatchStrings(strings_list, &encodings); - size_t batch_size = strings_list.size(); - size_t seq_len = encodings[0].GetLen(); - for (auto&& encoding : encodings) { - std::cout << encoding.DebugString() << std::endl; - } - // 2. Initialize runtime - fastdeploy::RuntimeOption runtime_option; - runtime_option.SetModelPath("nano_static/model.pdmodel", - "nano_static/model.pdiparams"); - fastdeploy::Runtime runtime; - runtime.Init(runtime_option); - - // 3. Construct input vector - // 3.1 Convert encodings to input_ids, token_type_ids - std::vector input_ids, token_type_ids; - for (int i = 0; i < encodings.size(); ++i) { - auto&& curr_input_ids = encodings[i].GetIds(); - auto&& curr_type_ids = encodings[i].GetTypeIds(); - input_ids.insert(input_ids.end(), curr_input_ids.begin(), - curr_input_ids.end()); - token_type_ids.insert(token_type_ids.end(), curr_type_ids.begin(), - curr_type_ids.end()); - } - // 3.2 Set data to input vector - std::vector inputs(runtime.NumInputs()); - void* inputs_ptrs[] = {input_ids.data(), token_type_ids.data()}; - for (int i = 0; i < runtime.NumInputs(); ++i) { - inputs[i].SetExternalData({batch_size, seq_len}, - fastdeploy::FDDataType::INT64, inputs_ptrs[i]); - inputs[i].name = runtime.GetInputInfo(i).name; - } - - // 4. Infer - std::vector outputs(runtime.NumOutputs()); - runtime.Infer(inputs, &outputs); - - // 5. Postprocess - fastdeploy::FDTensor domain_probs, intent_probs; - fastdeploy::Softmax(outputs[0], &domain_probs); - fastdeploy::Softmax(outputs[1], &intent_probs); - - fastdeploy::FDTensor domain_max_probs, intent_max_probs; - fastdeploy::Max(domain_probs, &domain_max_probs, {-1}, true); - fastdeploy::Max(intent_probs, &intent_max_probs, {-1}, true); - - std::vector transition; - int num_tags; - LoadTransitionFromFile("joint_transition.txt", &transition, &num_tags); - fastdeploy::FDTensor trans; - trans.SetExternalData({num_tags, num_tags}, fastdeploy::FDDataType::FP32, - transition.data()); - - fastdeploy::FDTensor best_path; - ViterbiDecode(outputs[2], trans, &best_path); - // 6. Print result - domain_max_probs.PrintInfo(); - intent_max_probs.PrintInfo(); - - batch_size = best_path.shape[0]; - seq_len = best_path.shape[1]; - const int64_t* best_path_ptr = - reinterpret_cast(best_path.Data()); - for (int i = 0; i < batch_size; ++i) { - std::cout << "best_path[" << i << "] = "; - for (int j = 0; j < seq_len; ++j) { - std::cout << best_path_ptr[i * seq_len + j] << ", "; - } - std::cout << std::endl; - } - best_path.PrintInfo(); + auto predictor = + UIEModel("uie-base/inference.pdmodel", "uie-base/inference.pdiparams", + "uie-base/vocab.txt", 0.5, 2, 128, {"时间", "选手", "赛事名称"}); + fastdeploy::FDINFO << "After init predictor" << std::endl; + std::vector results; + predictor.Predict({"2月8日上午北京冬奥会自由式滑雪女子大跳台决赛中中国选手谷" + "爱凌以188.25分获得金牌!"}, + &results); return 0; } diff --git a/examples/text/information_extraction/ernie/cpp/uie.cc b/examples/text/information_extraction/ernie/cpp/uie.cc new file mode 100644 index 00000000000..3d1efd6e9c3 --- /dev/null +++ b/examples/text/information_extraction/ernie/cpp/uie.cc @@ -0,0 +1,287 @@ +// Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "uie.h" +#include +#include + +#include "utils/utf8.h" // faster_tokenizer helper funciton + +static std::string DBC2SBC(const std::string& content) { + std::string result; + size_t content_utf8_len = 0; + while (content_utf8_len < content.length()) { + uint32_t content_char; + auto content_char_width = faster_tokenizer::utils::UTF8ToUInt32( + content.data() + content_utf8_len, &content_char); + content_char = faster_tokenizer::utils::UTF8ToUnicode(content_char); + if (content_char == 0x3000) { + content_char = 0x0020; + } else { + content_char -= 0xfee0; + } + if (content_char >= 0x0021 && content_char <= 0x7e) { + result.append(content.data() + content_utf8_len, content_char_width); + } else { + char dst_char[5] = {0}; + uint32_t utf8_uint32 = + faster_tokenizer::utils::UnicodeToUTF8(content_char); + uint32_t utf8_char_count = + faster_tokenizer::utils::UnicodeToUTF8Char(utf8_uint32, dst_char); + dst_char[utf8_char_count] = '\0'; + result.append(dst_char); + } + content_utf8_len += content_char_width; + } + return result; +} + +void Schema::CreateRoot(const std::string& name) { + root_ = fastdeploy::utils::make_unique(name); +} + +Schema::Schema(const std::string& schema, const std::string& name) { + CreateRoot(name); + root_->AddChild(schema); +} + +Schema::Schema(const std::vector& schema_list, + const std::string& name) { + CreateRoot(name); + for (const auto& schema : schema_list) { + root_->AddChild(schema); + } +} + +Schema::Schema( + const std::unordered_map>& schema_map, + const std::string& name) { + CreateRoot(name); + for (auto& schema_item : schema_map) { + root_->AddChild(schema_item.first, schema_item.second); + } +} + +UIEModel::UIEModel(const std::string& model_file, + const std::string& params_file, + const std::string& vocab_file, double position_prob, + int64_t batch_size, size_t max_length, + const std::vector& schema) + : max_length_(max_length), + position_prob_(position_prob), + tokenizer_(vocab_file), + batch_size_(batch_size) { + runtime_option_.SetModelPath(model_file, params_file); + runtime_.Init(runtime_option_); + SetSchema(schema); + tokenizer_.EnableTruncMethod( + max_length, 0, faster_tokenizer::core::Direction::RIGHT, + faster_tokenizer::core::TruncStrategy::LONGEST_FIRST); +} + +UIEModel::UIEModel( + const std::string& model_file, const std::string& params_file, + const std::string& vocab_file, double position_prob, int64_t batch_size, + size_t max_length, + const std::unordered_map>& schema) + : max_length_(max_length), + position_prob_(position_prob), + tokenizer_(vocab_file), + batch_size_(batch_size) { + runtime_option_.SetModelPath(model_file, params_file); + runtime_.Init(runtime_option_); + SetSchema(schema); + tokenizer_.EnableTruncMethod( + max_length, 0, faster_tokenizer::core::Direction::RIGHT, + faster_tokenizer::core::TruncStrategy::LONGEST_FIRST); +} + +void UIEModel::SetSchema(const std::vector& schema) { + schema_ = fastdeploy::utils::make_unique(schema); +} + +void UIEModel::SetSchema( + const std::unordered_map>& schema) { + schema_ = fastdeploy::utils::make_unique(schema); +} + +void UIEModel::AutoSplitter( + const std::vector& texts, size_t max_length, + std::vector* short_texts, + std::unordered_map>* input_mapping) { + size_t cnt_org = 0; + size_t cnt_short = 0; + for (auto& text : texts) { + auto text_len = text.length(); + if (text_len <= max_length) { + short_texts->push_back(text); + if (input_mapping->count(cnt_org) == 0) { + (*input_mapping)[cnt_org] = {cnt_short}; + } else { + (*input_mapping)[cnt_org].push_back(cnt_short); + } + cnt_short += 1; + } else { + for (size_t start = 0; start < text_len; start += max_length) { + size_t end = start + max_length; + if (end > text_len) { + end = text_len; + } + short_texts->emplace_back(text.data() + start, end - start); + } + auto short_idx = cnt_short; + cnt_short += text_len / max_length; + if (text_len % max_length != 0) { + ++cnt_short; + } + std::vector temp_text_id(cnt_short - short_idx); + std::iota(temp_text_id.begin(), temp_text_id.end(), short_idx); + if (input_mapping->count(cnt_org) == 0) { + (*input_mapping)[cnt_org] = std::move(temp_text_id); + } else { + (*input_mapping)[cnt_org].insert((*input_mapping)[cnt_org].end(), + temp_text_id.begin(), + temp_text_id.end()); + } + } + cnt_org += 1; + } +} + +void UIEModel::PredictUIEInput(const std::vector& input_texts, + const std::vector& prompts) { + // 1. Shortten the input texts and prompts + auto max_predict_len = + max_length_ - 3 - + std::max_element(prompts.begin(), prompts.end(), + [](const std::string& lhs, const std::string& rhs) { + return lhs.length() < rhs.length(); + }) + ->length(); + std::vector short_texts; + std::unordered_map> input_mapping; + AutoSplitter(input_texts, max_predict_len, &short_texts, &input_mapping); + + std::vector short_texts_prompts; + for (auto& item : input_mapping) { + short_texts_prompts.insert(short_texts_prompts.end(), item.second.size(), + prompts[item.first]); + } + std::vector text_pair_input; + for (int i = 0; i < short_texts.size(); ++i) { + text_pair_input.emplace_back(std::pair( + short_texts[i], short_texts_prompts[i])); + } + + // 2. Tokenize the short texts and short prompts + std::vector encodings; + tokenizer_.EncodeBatchStrings(text_pair_input, &encodings); + + // 3. Construct the input vector tensor + // 3.1 Convert encodings to input_ids, token_type_ids, position_ids, attn_mask + std::vector input_ids, token_type_ids, position_ids, attn_mask; + for (int i = 0; i < encodings.size(); ++i) { + auto&& curr_input_ids = encodings[i].GetIds(); + auto&& curr_type_ids = encodings[i].GetTypeIds(); + auto&& curr_attn_mask = encodings[i].GetAttentionMask(); + input_ids.insert(input_ids.end(), curr_input_ids.begin(), + curr_input_ids.end()); + token_type_ids.insert(token_type_ids.end(), curr_type_ids.begin(), + curr_type_ids.end()); + attn_mask.insert(attn_mask.end(), curr_attn_mask.begin(), + curr_attn_mask.end()); + std::vector curr_position_ids(curr_input_ids.size()); + std::iota(curr_position_ids.begin(), curr_position_ids.end(), 0); + position_ids.insert(position_ids.end(), curr_position_ids.begin(), + curr_position_ids.end()); + } + // 3.2 Set data to input vector + int64_t seq_len = input_ids.size() / input_texts.size(); + std::vector inputs(runtime_.NumInputs()); + int64_t* inputs_ptrs[] = {input_ids.data(), token_type_ids.data(), + position_ids.data(), attn_mask.data()}; + std::vector start_probs, end_probs; + + std::vector outputs(runtime_.NumOutputs()); + for (int i = 0; i * batch_size_ < input_texts.size(); ++i) { + auto curr_bz = batch_size_; + if ((i + 1) * batch_size_ > input_texts.size()) { + curr_bz = (i + 1) * batch_size_ - input_texts.size(); + } + for (int j = 0; j < runtime_.NumInputs(); ++j) { + inputs[j].SetExternalData({curr_bz, seq_len}, + fastdeploy::FDDataType::INT64, + inputs_ptrs[j] + i * batch_size_ * seq_len); + inputs[j].name = runtime_.GetInputInfo(j).name; + } + // 4. Infer + runtime_.Infer(inputs, &outputs); + auto* start_prob = reinterpret_cast(outputs[0].Data()); + auto* end_prob = reinterpret_cast(outputs[1].Data()); + start_probs.insert(start_probs.end(), start_prob, + start_prob + outputs[0].Numel()); + end_probs.insert(end_probs.end(), end_prob, end_prob + outputs[0].Numel()); + } + + // 5. Postprocess +} + +void UIEModel::Predict(const std::vector& texts, + std::vector* results) { + std::queue nodes; + for (auto& node : schema_->root_->children_) { + nodes.push(node); + } + while (!nodes.empty()) { + auto& node = nodes.front(); + nodes.pop(); + std::vector> input_mapping; + size_t idx = 0; + std::vector input_texts; + std::vector prompts; + // 1. Construct input data from raw text + if (node.prefix_.empty()) { + for (int i = 0; i < texts.size(); ++i) { + input_texts.push_back(texts[i]); + prompts.push_back(DBC2SBC(node.name_)); + input_mapping.push_back({idx}); + idx += 1; + } + } else { + for (int i = 0; i < texts.size(); ++i) { + if (node.prefix_[i].size() == 0) { + input_mapping.push_back({}); + } else { + for (auto&& pre : node.prefix_[i]) { + input_texts.push_back(texts[i]); + prompts.push_back(DBC2SBC(pre + node.name_)); + } + input_mapping.push_back({}); + input_mapping.back().resize(node.prefix_[i].size()); + std::iota(input_mapping.back().begin(), input_mapping.back().end(), + idx); + idx += node.prefix_[i].size(); + } + } + } + + // 2. Predict from UIEInput + PredictUIEInput(input_texts, prompts); + + // 3. Postprocess + for (auto& node_child : node.children_) { + nodes.push(node_child); + } + } +} diff --git a/examples/text/information_extraction/ernie/cpp/uie.h b/examples/text/information_extraction/ernie/cpp/uie.h new file mode 100644 index 00000000000..9a74acfd1b7 --- /dev/null +++ b/examples/text/information_extraction/ernie/cpp/uie.h @@ -0,0 +1,102 @@ +// Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +#pragma once + +#include +#include +#include +#include "fastdeploy/fastdeploy_model.h" +#include "fastdeploy/utils/unique_ptr.h" +#include "tokenizers/ernie_faster_tokenizer.h" + +using namespace paddlenlp; + +struct SchemaNode { + std::string name_; + std::vector prefix_; + std::vector>> + relations_; + std::vector children_; + + explicit SchemaNode(const std::string& name) : name_(name) {} + void AddChild(const std::string& schema) { children_.emplace_back(schema); } + void AddChild(const std::string& schema, + const std::vector& children) { + SchemaNode schema_node(schema); + for (auto& child : children) { + schema_node.children_.emplace_back(child); + } + children_.emplace_back(schema_node); + } +}; + +struct Schema { + explicit Schema(const std::string& schema, const std::string& name = "root"); + explicit Schema(const std::vector& schema_list, + const std::string& name = "root"); + explicit Schema(const std::unordered_map< + std::string, std::vector>& schema_map, + const std::string& name = "root"); + + private: + void CreateRoot(const std::string& name); + std::unique_ptr root_; + friend class UIEModel; +}; + +struct UIEResult { + size_t start_; + size_t end_; + double probability_; + std::string text_; + std::unique_ptr relations_; +}; + +struct UIEInput { + std::string text_; + std::string prompt_; +}; + +struct UIEModel { + UIEModel(const std::string& model_file, const std::string& params_file, + const std::string& vocab_file, double position_prob, + int64_t batch_size, size_t max_length, + const std::vector& schema); + UIEModel( + const std::string& model_file, const std::string& params_file, + const std::string& vocab_file, double position_prob, int64_t batch_size, + size_t max_length, + const std::unordered_map>& schema); + void SetSchema(const std::vector& schema); + void SetSchema( + const std::unordered_map>& schema); + + void PredictUIEInput(const std::vector& input_texts, + const std::vector& prompts); + void Predict(const std::vector& texts, + std::vector* results); + + private: + void AutoSplitter( + const std::vector& texts, size_t max_length, + std::vector* short_texts, + std::unordered_map>* input_mapping); + fastdeploy::RuntimeOption runtime_option_; + fastdeploy::Runtime runtime_; + std::unique_ptr schema_; + size_t max_length_; + int64_t batch_size_; + double position_prob_; + faster_tokenizer::tokenizers_impl::ErnieFasterTokenizer tokenizer_; +}; From 54347580d51b302e5a2559ef626b24c060efb2dd Mon Sep 17 00:00:00 2001 From: zhoushunjie Date: Tue, 16 Aug 2022 12:04:09 +0800 Subject: [PATCH 02/17] remove batch size --- .../information_extraction/ernie/cpp/infer.cc | 2 +- .../information_extraction/ernie/cpp/uie.cc | 48 ++++++++----------- .../information_extraction/ernie/cpp/uie.h | 7 +-- 3 files changed, 22 insertions(+), 35 deletions(-) diff --git a/examples/text/information_extraction/ernie/cpp/infer.cc b/examples/text/information_extraction/ernie/cpp/infer.cc index ce9313a0048..36a34a2ef2c 100644 --- a/examples/text/information_extraction/ernie/cpp/infer.cc +++ b/examples/text/information_extraction/ernie/cpp/infer.cc @@ -25,7 +25,7 @@ using namespace paddlenlp; int main() { auto predictor = UIEModel("uie-base/inference.pdmodel", "uie-base/inference.pdiparams", - "uie-base/vocab.txt", 0.5, 2, 128, {"时间", "选手", "赛事名称"}); + "uie-base/vocab.txt", 0.5, 128, {"时间", "选手", "赛事名称"}); fastdeploy::FDINFO << "After init predictor" << std::endl; std::vector results; predictor.Predict({"2月8日上午北京冬奥会自由式滑雪女子大跳台决赛中中国选手谷" diff --git a/examples/text/information_extraction/ernie/cpp/uie.cc b/examples/text/information_extraction/ernie/cpp/uie.cc index 3d1efd6e9c3..93c5adfeee1 100644 --- a/examples/text/information_extraction/ernie/cpp/uie.cc +++ b/examples/text/information_extraction/ernie/cpp/uie.cc @@ -76,12 +76,10 @@ Schema::Schema( UIEModel::UIEModel(const std::string& model_file, const std::string& params_file, const std::string& vocab_file, double position_prob, - int64_t batch_size, size_t max_length, - const std::vector& schema) + size_t max_length, const std::vector& schema) : max_length_(max_length), position_prob_(position_prob), - tokenizer_(vocab_file), - batch_size_(batch_size) { + tokenizer_(vocab_file) { runtime_option_.SetModelPath(model_file, params_file); runtime_.Init(runtime_option_); SetSchema(schema); @@ -92,13 +90,11 @@ UIEModel::UIEModel(const std::string& model_file, UIEModel::UIEModel( const std::string& model_file, const std::string& params_file, - const std::string& vocab_file, double position_prob, int64_t batch_size, - size_t max_length, + const std::string& vocab_file, double position_prob, size_t max_length, const std::unordered_map>& schema) : max_length_(max_length), position_prob_(position_prob), - tokenizer_(vocab_file), - batch_size_(batch_size) { + tokenizer_(vocab_file) { runtime_option_.SetModelPath(model_file, params_file); runtime_.Init(runtime_option_); SetSchema(schema); @@ -207,32 +203,26 @@ void UIEModel::PredictUIEInput(const std::vector& input_texts, curr_position_ids.end()); } // 3.2 Set data to input vector - int64_t seq_len = input_ids.size() / input_texts.size(); + int64_t batch_size = input_texts.size(); + int64_t seq_len = input_ids.size() / batch_size; std::vector inputs(runtime_.NumInputs()); int64_t* inputs_ptrs[] = {input_ids.data(), token_type_ids.data(), position_ids.data(), attn_mask.data()}; - std::vector start_probs, end_probs; + for (int i = 0; i < runtime_.NumInputs(); ++i) { + inputs[i].SetExternalData({batch_size, seq_len}, + fastdeploy::FDDataType::INT64, inputs_ptrs[i]); + inputs[i].name = runtime_.GetInputInfo(i).name; + } + std::vector start_probs, end_probs; std::vector outputs(runtime_.NumOutputs()); - for (int i = 0; i * batch_size_ < input_texts.size(); ++i) { - auto curr_bz = batch_size_; - if ((i + 1) * batch_size_ > input_texts.size()) { - curr_bz = (i + 1) * batch_size_ - input_texts.size(); - } - for (int j = 0; j < runtime_.NumInputs(); ++j) { - inputs[j].SetExternalData({curr_bz, seq_len}, - fastdeploy::FDDataType::INT64, - inputs_ptrs[j] + i * batch_size_ * seq_len); - inputs[j].name = runtime_.GetInputInfo(j).name; - } - // 4. Infer - runtime_.Infer(inputs, &outputs); - auto* start_prob = reinterpret_cast(outputs[0].Data()); - auto* end_prob = reinterpret_cast(outputs[1].Data()); - start_probs.insert(start_probs.end(), start_prob, - start_prob + outputs[0].Numel()); - end_probs.insert(end_probs.end(), end_prob, end_prob + outputs[0].Numel()); - } + // 4. Infer + runtime_.Infer(inputs, &outputs); + auto* start_prob = reinterpret_cast(outputs[0].Data()); + auto* end_prob = reinterpret_cast(outputs[1].Data()); + start_probs.insert(start_probs.end(), start_prob, + start_prob + outputs[0].Numel()); + end_probs.insert(end_probs.end(), end_prob, end_prob + outputs[0].Numel()); // 5. Postprocess } diff --git a/examples/text/information_extraction/ernie/cpp/uie.h b/examples/text/information_extraction/ernie/cpp/uie.h index 9a74acfd1b7..583aeeb25ad 100644 --- a/examples/text/information_extraction/ernie/cpp/uie.h +++ b/examples/text/information_extraction/ernie/cpp/uie.h @@ -71,12 +71,10 @@ struct UIEInput { struct UIEModel { UIEModel(const std::string& model_file, const std::string& params_file, const std::string& vocab_file, double position_prob, - int64_t batch_size, size_t max_length, - const std::vector& schema); + size_t max_length, const std::vector& schema); UIEModel( const std::string& model_file, const std::string& params_file, - const std::string& vocab_file, double position_prob, int64_t batch_size, - size_t max_length, + const std::string& vocab_file, double position_prob, size_t max_length, const std::unordered_map>& schema); void SetSchema(const std::vector& schema); void SetSchema( @@ -96,7 +94,6 @@ struct UIEModel { fastdeploy::Runtime runtime_; std::unique_ptr schema_; size_t max_length_; - int64_t batch_size_; double position_prob_; faster_tokenizer::tokenizers_impl::ErnieFasterTokenizer tokenizer_; }; From f5537a9b404fc4e4b97122ae002f01fbff54c21f Mon Sep 17 00:00:00 2001 From: zhoushunjie Date: Tue, 16 Aug 2022 15:19:42 +0800 Subject: [PATCH 03/17] Add GetCandidateIdx --- .../information_extraction/ernie/cpp/uie.cc | 29 +++++++++++++++---- .../information_extraction/ernie/cpp/uie.h | 12 ++++++-- 2 files changed, 32 insertions(+), 9 deletions(-) diff --git a/examples/text/information_extraction/ernie/cpp/uie.cc b/examples/text/information_extraction/ernie/cpp/uie.cc index 93c5adfeee1..0e5a02f5f8f 100644 --- a/examples/text/information_extraction/ernie/cpp/uie.cc +++ b/examples/text/information_extraction/ernie/cpp/uie.cc @@ -75,7 +75,7 @@ Schema::Schema( UIEModel::UIEModel(const std::string& model_file, const std::string& params_file, - const std::string& vocab_file, double position_prob, + const std::string& vocab_file, float position_prob, size_t max_length, const std::vector& schema) : max_length_(max_length), position_prob_(position_prob), @@ -90,7 +90,7 @@ UIEModel::UIEModel(const std::string& model_file, UIEModel::UIEModel( const std::string& model_file, const std::string& params_file, - const std::string& vocab_file, double position_prob, size_t max_length, + const std::string& vocab_file, float position_prob, size_t max_length, const std::unordered_map>& schema) : max_length_(max_length), position_prob_(position_prob), @@ -155,6 +155,20 @@ void UIEModel::AutoSplitter( } } +void UIEModel::GetCandidateIdx( + const float* probs, int64_t batch_size, int64_t seq_len, + std::vector>>* candidate_idx_prob, + float threshold) const { + for (int i = 0; i < batch_size; ++i) { + candidate_idx_prob->push_back({}); + for (int j = 0; j < seq_len; ++j) { + if (probs[i * seq_len + j] > threshold) { + candidate_idx_prob->back().push_back({j, probs[i * seq_len + j]}); + } + } + } +} + void UIEModel::PredictUIEInput(const std::vector& input_texts, const std::vector& prompts) { // 1. Shortten the input texts and prompts @@ -214,17 +228,20 @@ void UIEModel::PredictUIEInput(const std::vector& input_texts, inputs[i].name = runtime_.GetInputInfo(i).name; } - std::vector start_probs, end_probs; std::vector outputs(runtime_.NumOutputs()); // 4. Infer runtime_.Infer(inputs, &outputs); auto* start_prob = reinterpret_cast(outputs[0].Data()); auto* end_prob = reinterpret_cast(outputs[1].Data()); - start_probs.insert(start_probs.end(), start_prob, - start_prob + outputs[0].Numel()); - end_probs.insert(end_probs.end(), end_prob, end_prob + outputs[0].Numel()); // 5. Postprocess + std::vector>> start_candidate_idx_prob, + end_candidate_idx_prob; + + GetCandidateIdx(start_prob, outputs[0].shape[0], outputs[0].shape[1], + &start_candidate_idx_prob, position_prob_); + GetCandidateIdx(end_prob, outputs[1].shape[0], outputs[1].shape[1], + &end_candidate_idx_prob, position_prob_); } void UIEModel::Predict(const std::vector& texts, diff --git a/examples/text/information_extraction/ernie/cpp/uie.h b/examples/text/information_extraction/ernie/cpp/uie.h index 583aeeb25ad..a6381812467 100644 --- a/examples/text/information_extraction/ernie/cpp/uie.h +++ b/examples/text/information_extraction/ernie/cpp/uie.h @@ -70,11 +70,11 @@ struct UIEInput { struct UIEModel { UIEModel(const std::string& model_file, const std::string& params_file, - const std::string& vocab_file, double position_prob, + const std::string& vocab_file, float position_prob, size_t max_length, const std::vector& schema); UIEModel( const std::string& model_file, const std::string& params_file, - const std::string& vocab_file, double position_prob, size_t max_length, + const std::string& vocab_file, float position_prob, size_t max_length, const std::unordered_map>& schema); void SetSchema(const std::vector& schema); void SetSchema( @@ -90,10 +90,16 @@ struct UIEModel { const std::vector& texts, size_t max_length, std::vector* short_texts, std::unordered_map>* input_mapping); + // Get idx of the last dimension in probability arrays, which is greater than + // a limitation. + void GetCandidateIdx( + const float* probs, int64_t batch_size, int64_t seq_len, + std::vector>>* candidate_idx_prob, + float threshold = 0.5) const; fastdeploy::RuntimeOption runtime_option_; fastdeploy::Runtime runtime_; std::unique_ptr schema_; size_t max_length_; - double position_prob_; + float position_prob_; faster_tokenizer::tokenizers_impl::ErnieFasterTokenizer tokenizer_; }; From 2647cf33e08b7f62bea89011782afab6c61678bc Mon Sep 17 00:00:00 2001 From: zhoushunjie Date: Wed, 17 Aug 2022 15:05:20 +0800 Subject: [PATCH 04/17] add GetCandidateIdx GetSpan GetSpanIdxAndProbs --- .../information_extraction/ernie/cpp/uie.cc | 56 +++++++++++++++++++ .../information_extraction/ernie/cpp/uie.h | 23 ++++++-- 2 files changed, 75 insertions(+), 4 deletions(-) diff --git a/examples/text/information_extraction/ernie/cpp/uie.cc b/examples/text/information_extraction/ernie/cpp/uie.cc index 0e5a02f5f8f..27c30510cde 100644 --- a/examples/text/information_extraction/ernie/cpp/uie.cc +++ b/examples/text/information_extraction/ernie/cpp/uie.cc @@ -169,6 +169,45 @@ void UIEModel::GetCandidateIdx( } } +bool UIEModel::IdxProbCmp::operator()( + const std::pair& lhs, + const std::pair& rhs) const { + if (lhs.first.first == rhs.first.first) { + return lhs.second.first < rhs.second.first; + } + return lhs.first.first < rhs.first.first; +} + +void UIEModel::GetSpan(const std::vector& start_idx_prob, + const std::vector& end_idx_prob, + SPAN_SET* span_set) const { + size_t start_pointer = 0; + size_t end_pointer = 0; + size_t len_start = start_idx_prob.size(); + size_t len_end = end_idx_prob.size(); + while (start_pointer < len_start && end_pointer < len_end) { + if (start_idx_prob[start_pointer].first == + end_idx_prob[end_pointer].first) { + span_set->insert(std::make_pair(start_idx_prob[start_pointer], + end_idx_prob[end_pointer])); + ++start_pointer; + ++end_pointer; + } else if (start_idx_prob[start_pointer].first < + end_idx_prob[end_pointer].first) { + span_set->insert(std::make_pair(start_idx_prob[start_pointer], + end_idx_prob[end_pointer])); + ++start_pointer; + } else { + ++end_pointer; + } + } +} +void UIEModel::GetSpanIdxAndProbs( + const SPAN_SET& span_set, + const faster_tokenizer::core::Offset& offset_mapping, + std::vector* span_idxs, + std::vector* probs) const {} + void UIEModel::PredictUIEInput(const std::vector& input_texts, const std::vector& prompts) { // 1. Shortten the input texts and prompts @@ -201,21 +240,30 @@ void UIEModel::PredictUIEInput(const std::vector& input_texts, // 3. Construct the input vector tensor // 3.1 Convert encodings to input_ids, token_type_ids, position_ids, attn_mask std::vector input_ids, token_type_ids, position_ids, attn_mask; + std::vector offset_mapping; for (int i = 0; i < encodings.size(); ++i) { auto&& curr_input_ids = encodings[i].GetIds(); auto&& curr_type_ids = encodings[i].GetTypeIds(); auto&& curr_attn_mask = encodings[i].GetAttentionMask(); + auto&& curr_offsets = encodings[i].GetOffsets(); input_ids.insert(input_ids.end(), curr_input_ids.begin(), curr_input_ids.end()); token_type_ids.insert(token_type_ids.end(), curr_type_ids.begin(), curr_type_ids.end()); attn_mask.insert(attn_mask.end(), curr_attn_mask.begin(), curr_attn_mask.end()); + offset_mapping.insert(offset_mapping.end(), curr_offsets.begin(), + curr_offsets.end()); std::vector curr_position_ids(curr_input_ids.size()); std::iota(curr_position_ids.begin(), curr_position_ids.end(), 0); position_ids.insert(position_ids.end(), curr_position_ids.begin(), curr_position_ids.end()); } + for (auto&& offset : offset_mapping) { + fastdeploy::FDINFO << "offset = " << offset.first << ", " << offset.second + << std::endl; + } + fastdeploy::FDINFO << std::endl; // 3.2 Set data to input vector int64_t batch_size = input_texts.size(); int64_t seq_len = input_ids.size() / batch_size; @@ -242,6 +290,14 @@ void UIEModel::PredictUIEInput(const std::vector& input_texts, &start_candidate_idx_prob, position_prob_); GetCandidateIdx(end_prob, outputs[1].shape[0], outputs[1].shape[1], &end_candidate_idx_prob, position_prob_); + SPAN_SET span_list; + for (int i = 0; i < batch_size; ++i) { + GetSpan(start_candidate_idx_prob[i], end_candidate_idx_prob[i], &span_list); + // sentence_id, prob = get_id_and_prob(span_list, offset_map) + // sentence_ids.append(sentence_id) + // probs.append(prob) + span_list.clear(); + } } void UIEModel::Predict(const std::vector& texts, diff --git a/examples/text/information_extraction/ernie/cpp/uie.h b/examples/text/information_extraction/ernie/cpp/uie.h index a6381812467..c909febebb3 100644 --- a/examples/text/information_extraction/ernie/cpp/uie.h +++ b/examples/text/information_extraction/ernie/cpp/uie.h @@ -13,6 +13,7 @@ // limitations under the License. #pragma once +#include #include #include #include @@ -69,6 +70,7 @@ struct UIEInput { }; struct UIEModel { + public: UIEModel(const std::string& model_file, const std::string& params_file, const std::string& vocab_file, float position_prob, size_t max_length, const std::vector& schema); @@ -86,16 +88,29 @@ struct UIEModel { std::vector* results); private: + using IDX_PROB = std::pair; + struct IdxProbCmp { + bool operator()(const std::pair& lhs, + const std::pair& rhs) const; + }; + using SPAN_SET = std::set, IdxProbCmp>; void AutoSplitter( const std::vector& texts, size_t max_length, std::vector* short_texts, std::unordered_map>* input_mapping); // Get idx of the last dimension in probability arrays, which is greater than // a limitation. - void GetCandidateIdx( - const float* probs, int64_t batch_size, int64_t seq_len, - std::vector>>* candidate_idx_prob, - float threshold = 0.5) const; + void GetCandidateIdx(const float* probs, int64_t batch_size, int64_t seq_len, + std::vector>* candidate_idx_prob, + float threshold = 0.5) const; + void GetSpan(const std::vector& start_idx_prob, + const std::vector& end_idx_prob, + SPAN_SET* span_set) const; + void GetSpanIdxAndProbs( + const SPAN_SET& span_set, + const faster_tokenizer::core::Offset& offset_mapping, + std::vector* span_idxs, + std::vector* probs) const; fastdeploy::RuntimeOption runtime_option_; fastdeploy::Runtime runtime_; std::unique_ptr schema_; From 48b384776886a5b34f311dd33208c580f2cc3cc5 Mon Sep 17 00:00:00 2001 From: zhoushunjie Date: Mon, 22 Aug 2022 17:09:30 +0800 Subject: [PATCH 05/17] Add Predict of UIEModel --- .../information_extraction/ernie/cpp/infer.cc | 2 +- .../information_extraction/ernie/cpp/uie.cc | 280 ++++++++++++++++-- .../information_extraction/ernie/cpp/uie.h | 60 ++-- 3 files changed, 291 insertions(+), 51 deletions(-) diff --git a/examples/text/information_extraction/ernie/cpp/infer.cc b/examples/text/information_extraction/ernie/cpp/infer.cc index 36a34a2ef2c..15155e908c1 100644 --- a/examples/text/information_extraction/ernie/cpp/infer.cc +++ b/examples/text/information_extraction/ernie/cpp/infer.cc @@ -27,7 +27,7 @@ int main() { UIEModel("uie-base/inference.pdmodel", "uie-base/inference.pdiparams", "uie-base/vocab.txt", 0.5, 128, {"时间", "选手", "赛事名称"}); fastdeploy::FDINFO << "After init predictor" << std::endl; - std::vector results; + std::vector>> results; predictor.Predict({"2月8日上午北京冬奥会自由式滑雪女子大跳台决赛中中国选手谷" "爱凌以188.25分获得金牌!"}, &results); diff --git a/examples/text/information_extraction/ernie/cpp/uie.cc b/examples/text/information_extraction/ernie/cpp/uie.cc index 27c30510cde..b4be7788932 100644 --- a/examples/text/information_extraction/ernie/cpp/uie.cc +++ b/examples/text/information_extraction/ernie/cpp/uie.cc @@ -14,6 +14,8 @@ #include "uie.h" #include +#include +#include #include #include "utils/utf8.h" // faster_tokenizer helper funciton @@ -31,7 +33,7 @@ static std::string DBC2SBC(const std::string& content) { } else { content_char -= 0xfee0; } - if (content_char >= 0x0021 && content_char <= 0x7e) { + if (!(content_char >= 0x0021 && content_char <= 0x7e)) { result.append(content.data() + content_utf8_len, content_char_width); } else { char dst_char[5] = {0}; @@ -39,14 +41,35 @@ static std::string DBC2SBC(const std::string& content) { faster_tokenizer::utils::UnicodeToUTF8(content_char); uint32_t utf8_char_count = faster_tokenizer::utils::UnicodeToUTF8Char(utf8_uint32, dst_char); - dst_char[utf8_char_count] = '\0'; - result.append(dst_char); + result.append(dst_char, utf8_char_count); } content_utf8_len += content_char_width; } return result; } +// Will remove to faster_tokenizer utils +static void CharToByteOffsetMap(const std::string& seq, + std::vector* offset_mapping) { + std::wstring_convert, char32_t> conv; + std::u32string u32seq = conv.from_bytes(seq); + uint32_t index = 0; + offset_mapping->reserve(u32seq.length() * 4); + for (int i = 0; i < u32seq.length(); ++i) { + offset_mapping->push_back(index); + auto utf8_len = faster_tokenizer::utils::GetUTF8CharLen(u32seq[i]); + index += utf8_len; + } + offset_mapping->push_back(index); +} + +std::ostream& operator<<(std::ostream& os, const UIEResult& result) { + os << "text = " << result.text_ << "\nprobability = " << result.probability_ + << "\nstart = " << result.start_ << "\nend = " << result.end_; + os << std::endl; + return os; +} + void Schema::CreateRoot(const std::string& name) { root_ = fastdeploy::utils::make_unique(name); } @@ -204,12 +227,144 @@ void UIEModel::GetSpan(const std::vector& start_idx_prob, } void UIEModel::GetSpanIdxAndProbs( const SPAN_SET& span_set, - const faster_tokenizer::core::Offset& offset_mapping, - std::vector* span_idxs, - std::vector* probs) const {} + const std::vector& offset_mapping, + std::vector* span_idxs, std::vector* probs) const { + auto first_sep_idx = + std::find_if(offset_mapping.begin() + 1, offset_mapping.end(), + [](const faster_tokenizer::core::Offset& offset) { + return offset == faster_tokenizer::core::Offset(0, 0); + }); + auto prompt_end_token_id = + std::distance(offset_mapping.begin(), first_sep_idx) - 1; + for (auto&& span_item : span_set) { + probs->push_back(span_item.first.second * span_item.second.second); + auto start_id = offset_mapping[span_item.first.first].first; + auto end_id = offset_mapping[span_item.second.first].second; + bool is_prompt = span_item.second.first <= prompt_end_token_id && + span_item.second.first > 0; + span_idxs->push_back({{start_id, end_id}, is_prompt}); + } +} + +void UIEModel::ConvertSpanToUIEResult( + const std::vector& texts, + const std::vector& prompts, + const std::vector>& span_idxs, + const std::vector>& probs, + std::vector>* results) const { + auto batch_size = texts.size(); + for (int i = 0; i < batch_size; ++i) { + std::vector result_list; + if (span_idxs[i].size() == 0) { + results->push_back({}); + continue; + } + auto&& text = texts[i]; + auto&& prompt = prompts[i]; + for (int j = 0; j < span_idxs[i].size(); ++j) { + auto start = span_idxs[i][j].offset_.first; + auto end = span_idxs[i][j].offset_.second; + std::string span_text; + std::vector offset_mapping; + if (span_idxs[i][j].is_prompt_) { + CharToByteOffsetMap(prompt, &offset_mapping); + auto byte_start = offset_mapping[start]; + auto byte_end = offset_mapping[end]; + span_text = prompt.substr(byte_start, byte_end - byte_start); + // Indicate cls task + start = 0; + end = 0; + } else { + CharToByteOffsetMap(text, &offset_mapping); + auto byte_start = offset_mapping[start]; + auto byte_end = offset_mapping[end]; + span_text = text.substr(byte_start, byte_end - byte_start); + } + result_list.emplace_back(start, end, probs[i][j], span_text); + } + results->push_back(result_list); + } +} + +void UIEModel::AutoJoiner( + const std::vector& short_texts, + const std::unordered_map>& input_mapping, + std::vector>* results) { + bool is_cls_task = false; + // 1. Detect if it's a cls task + for (auto&& short_result : *results) { + if (short_result.size() == 0) { + continue; + } else if (short_result[0].start_ == 0 && short_result[0].end_) { + is_cls_task = true; + break; + } else { + break; + } + } + // 2. Get the final result + std::vector> final_result; + if (is_cls_task) { + for (auto&& input_mapping_item : input_mapping) { + auto curr_mapping = input_mapping_item.second; + std::unordered_map> cls_options; + for (auto&& result_idx : curr_mapping) { + if ((*results)[result_idx].size() == 0) { + continue; + } + auto&& text = (*results)[result_idx].front().text_; + auto&& probability = (*results)[result_idx].front().probability_; + if (cls_options.count(text) == 0) { + cls_options[text] = std::make_pair(1, probability); + } else { + cls_options[text].first += 1; + cls_options[text].second += probability; + } + } + std::vector result_list; + if (cls_options.size() > 0) { + auto max_iter = std::max_element( + cls_options.begin(), cls_options.end(), + [](const std::pair>& lhs, + const std::pair>& rhs) { + return lhs.second.second < rhs.second.second; + }); + result_list.emplace_back( + 0, 0, max_iter->second.second / max_iter->second.first, + max_iter->first); + } + final_result.push_back(result_list); + } + } else { + for (auto&& input_mapping_item : input_mapping) { + auto curr_mapping = input_mapping_item.second; + size_t offset = 0; + std::vector result_list; + for (auto&& result_idx : curr_mapping) { + if (result_idx == 0) { + result_list = std::move((*results)[result_idx]); + offset += faster_tokenizer::utils::GetUnicodeLenFromUTF8( + short_texts[result_idx].c_str(), short_texts[result_idx].size()); + } else { + for (auto&& curr_result : (*results)[result_idx]) { + curr_result.start_ += offset; + curr_result.end_ += offset; + } + offset += faster_tokenizer::utils::GetUnicodeLenFromUTF8( + short_texts[result_idx].c_str(), short_texts[result_idx].size()); + result_list.insert(result_list.end(), (*results)[result_idx].begin(), + (*results)[result_idx].end()); + } + } + final_result.push_back(result_list); + } + } + *results = std::move(final_result); +} void UIEModel::PredictUIEInput(const std::vector& input_texts, - const std::vector& prompts) { + const std::vector& prompts, + std::vector>* results) { // 1. Shortten the input texts and prompts auto max_predict_len = max_length_ - 3 - @@ -230,7 +385,7 @@ void UIEModel::PredictUIEInput(const std::vector& input_texts, std::vector text_pair_input; for (int i = 0; i < short_texts.size(); ++i) { text_pair_input.emplace_back(std::pair( - short_texts[i], short_texts_prompts[i])); + short_texts_prompts[i], short_texts[i])); } // 2. Tokenize the short texts and short prompts @@ -240,7 +395,7 @@ void UIEModel::PredictUIEInput(const std::vector& input_texts, // 3. Construct the input vector tensor // 3.1 Convert encodings to input_ids, token_type_ids, position_ids, attn_mask std::vector input_ids, token_type_ids, position_ids, attn_mask; - std::vector offset_mapping; + std::vector> offset_mapping; for (int i = 0; i < encodings.size(); ++i) { auto&& curr_input_ids = encodings[i].GetIds(); auto&& curr_type_ids = encodings[i].GetTypeIds(); @@ -252,20 +407,15 @@ void UIEModel::PredictUIEInput(const std::vector& input_texts, curr_type_ids.end()); attn_mask.insert(attn_mask.end(), curr_attn_mask.begin(), curr_attn_mask.end()); - offset_mapping.insert(offset_mapping.end(), curr_offsets.begin(), - curr_offsets.end()); + offset_mapping.push_back(curr_offsets); std::vector curr_position_ids(curr_input_ids.size()); std::iota(curr_position_ids.begin(), curr_position_ids.end(), 0); position_ids.insert(position_ids.end(), curr_position_ids.begin(), curr_position_ids.end()); } - for (auto&& offset : offset_mapping) { - fastdeploy::FDINFO << "offset = " << offset.first << ", " << offset.second - << std::endl; - } - fastdeploy::FDINFO << std::endl; + // 3.2 Set data to input vector - int64_t batch_size = input_texts.size(); + int64_t batch_size = short_texts.size(); int64_t seq_len = input_ids.size() / batch_size; std::vector inputs(runtime_.NumInputs()); int64_t* inputs_ptrs[] = {input_ids.data(), token_type_ids.data(), @@ -290,18 +440,23 @@ void UIEModel::PredictUIEInput(const std::vector& input_texts, &start_candidate_idx_prob, position_prob_); GetCandidateIdx(end_prob, outputs[1].shape[0], outputs[1].shape[1], &end_candidate_idx_prob, position_prob_); - SPAN_SET span_list; + SPAN_SET span_set; + std::vector> probs(batch_size); + std::vector> span_idxs(batch_size); for (int i = 0; i < batch_size; ++i) { - GetSpan(start_candidate_idx_prob[i], end_candidate_idx_prob[i], &span_list); - // sentence_id, prob = get_id_and_prob(span_list, offset_map) - // sentence_ids.append(sentence_id) - // probs.append(prob) - span_list.clear(); + GetSpan(start_candidate_idx_prob[i], end_candidate_idx_prob[i], &span_set); + GetSpanIdxAndProbs(span_set, offset_mapping[i], &span_idxs[i], &probs[i]); + span_set.clear(); } + ConvertSpanToUIEResult(short_texts, short_texts_prompts, span_idxs, probs, + results); + AutoJoiner(short_texts, input_mapping, results); } -void UIEModel::Predict(const std::vector& texts, - std::vector* results) { +void UIEModel::Predict( + const std::vector& texts, + std::vector>>* + results) { std::queue nodes; for (auto& node : schema_->root_->children_) { nodes.push(node); @@ -330,20 +485,89 @@ void UIEModel::Predict(const std::vector& texts, input_texts.push_back(texts[i]); prompts.push_back(DBC2SBC(pre + node.name_)); } + auto prefix_len = node.prefix_[i].size(); input_mapping.push_back({}); - input_mapping.back().resize(node.prefix_[i].size()); + input_mapping.back().resize(prefix_len); std::iota(input_mapping.back().begin(), input_mapping.back().end(), idx); - idx += node.prefix_[i].size(); + idx += prefix_len; } } } // 2. Predict from UIEInput - PredictUIEInput(input_texts, prompts); + std::vector> results_list; + PredictUIEInput(input_texts, prompts, &results_list); // 3. Postprocess + std::vector> relations; + relations.resize(texts.size()); + if (node.relations_.size() == 0) { + for (int i = 0; i < input_mapping.size(); ++i) { + auto&& input_mapping_item = input_mapping[i]; + auto& curr_result = (*results)[i]; + for (auto&& idx : input_mapping_item) { + if (results_list[idx].size() == 0) { + continue; + } + if (curr_result.count(node.name_) == 0) { + curr_result[node.name_] = std::move(results_list[idx]); + } else { + curr_result[node.name_].insert(curr_result[node.name_].end(), + results_list[idx].begin(), + results_list[idx].end()); + } + } + if (curr_result.count(node.name_) > 0) { + for (auto&& curr_result_ref : curr_result[node.name_]) { + relations[i].push_back(&curr_result_ref); + } + } + } + } else { + auto& new_relations = node.relations_; + for (int i = 0; i < input_mapping.size(); ++i) { + auto&& input_mapping_item = input_mapping[i]; + for (int j = 0; j < input_mapping_item.size(); ++j) { + auto idx = input_mapping_item[j]; + if (results_list[idx].size() == 0) { + continue; + } + if (new_relations[i][j]->relation_.count(node.name_) == 0) { + new_relations[i][j]->relation_[node.name_] = + std::move(results_list[idx]); + } else { + auto& curr_result = new_relations[i][j]->relation_[node.name_]; + curr_result.insert(curr_result.end(), results_list[idx].begin(), + results_list[idx].end()); + } + } + } + for (int i = 0; i < new_relations.size(); ++i) { + for (int j = 0; j < new_relations[i].size(); ++j) { + if (new_relations[i][j]->relation_.count(node.name_)) { + auto& curr_relation = new_relations[i][j]->relation_[node.name_]; + for (auto&& curr_result_ref : curr_relation) { + relations[i].push_back(&curr_result_ref); + } + } + } + } + } + + std::vector> prefix(texts.size()); + for (int i = 0; i < input_mapping.size(); ++i) { + auto&& input_mapping_item = input_mapping[i]; + for (auto&& idx : input_mapping_item) { + for (int j = 0; j < results_list[idx].size(); ++j) { + prefix[i].push_back(results_list[idx][j].text_ + "\u7684"); + } + } + } + for (auto& node_child : node.children_) { + node_child.relations_ = std::move(relations); + node_child.prefix_ = std::move(prefix); nodes.push(node_child); } } diff --git a/examples/text/information_extraction/ernie/cpp/uie.h b/examples/text/information_extraction/ernie/cpp/uie.h index c909febebb3..61ab0319bcb 100644 --- a/examples/text/information_extraction/ernie/cpp/uie.h +++ b/examples/text/information_extraction/ernie/cpp/uie.h @@ -13,6 +13,7 @@ // limitations under the License. #pragma once +#include #include #include #include @@ -23,11 +24,23 @@ using namespace paddlenlp; +struct UIEResult { + size_t start_; + size_t end_; + double probability_; + std::string text_; + std::unordered_map> relation_; + UIEResult() = default; + UIEResult(size_t start, size_t end, double probability, std::string text) + : start_(start), end_(end), probability_(probability), text_(text) {} +}; + +std::ostream& operator<<(std::ostream& os, const UIEResult& result); + struct SchemaNode { std::string name_; - std::vector prefix_; - std::vector>> - relations_; + std::vector> prefix_; + std::vector> relations_; std::vector children_; explicit SchemaNode(const std::string& name) : name_(name) {} @@ -56,19 +69,6 @@ struct Schema { friend class UIEModel; }; -struct UIEResult { - size_t start_; - size_t end_; - double probability_; - std::string text_; - std::unique_ptr relations_; -}; - -struct UIEInput { - std::string text_; - std::string prompt_; -}; - struct UIEModel { public: UIEModel(const std::string& model_file, const std::string& params_file, @@ -83,9 +83,12 @@ struct UIEModel { const std::unordered_map>& schema); void PredictUIEInput(const std::vector& input_texts, - const std::vector& prompts); - void Predict(const std::vector& texts, - std::vector* results); + const std::vector& prompts, + std::vector>* results); + void Predict( + const std::vector& texts, + std::vector>>* + results); private: using IDX_PROB = std::pair; @@ -94,10 +97,18 @@ struct UIEModel { const std::pair& rhs) const; }; using SPAN_SET = std::set, IdxProbCmp>; + struct SpanIdx { + faster_tokenizer::core::Offset offset_; + bool is_prompt_; + }; void AutoSplitter( const std::vector& texts, size_t max_length, std::vector* short_texts, std::unordered_map>* input_mapping); + void AutoJoiner( + const std::vector& short_texts, + const std::unordered_map>& input_mapping, + std::vector>* results); // Get idx of the last dimension in probability arrays, which is greater than // a limitation. void GetCandidateIdx(const float* probs, int64_t batch_size, int64_t seq_len, @@ -108,9 +119,14 @@ struct UIEModel { SPAN_SET* span_set) const; void GetSpanIdxAndProbs( const SPAN_SET& span_set, - const faster_tokenizer::core::Offset& offset_mapping, - std::vector* span_idxs, - std::vector* probs) const; + const std::vector& offset_mapping, + std::vector* span_idxs, std::vector* probs) const; + void ConvertSpanToUIEResult( + const std::vector& texts, + const std::vector& prompts, + const std::vector>& span_idxs, + const std::vector>& probs, + std::vector>* results) const; fastdeploy::RuntimeOption runtime_option_; fastdeploy::Runtime runtime_; std::unique_ptr schema_; From c9c3b69d6da250e658813ebae44af3d38c296fe5 Mon Sep 17 00:00:00 2001 From: zhoushunjie Date: Mon, 22 Aug 2022 21:11:03 +0800 Subject: [PATCH 06/17] Add relation schema --- .../information_extraction/ernie/cpp/infer.cc | 14 +++ .../information_extraction/ernie/cpp/uie.cc | 104 ++++++++++++++---- .../information_extraction/ernie/cpp/uie.h | 22 +++- 3 files changed, 116 insertions(+), 24 deletions(-) diff --git a/examples/text/information_extraction/ernie/cpp/infer.cc b/examples/text/information_extraction/ernie/cpp/infer.cc index 15155e908c1..a8d373850ef 100644 --- a/examples/text/information_extraction/ernie/cpp/infer.cc +++ b/examples/text/information_extraction/ernie/cpp/infer.cc @@ -31,5 +31,19 @@ int main() { predictor.Predict({"2月8日上午北京冬奥会自由式滑雪女子大跳台决赛中中国选手谷" "爱凌以188.25分获得金牌!"}, &results); + std::cout << results << std::endl; + + // schema for relation extraction + // schema = {'竞赛名称': ['主办方', '承办方', '已举办次数']} + predictor.SetSchema({{"竞赛名称", + {SchemaNode("主办方"), SchemaNode("承办方"), + SchemaNode("已举办次数")}}}); + results.clear(); + predictor.Predict( + {"2022语言与智能技术竞赛由中国中文信息学会和中国计算机学会联合主办,百度" + "公司、中国中文信息学会评测工作委员会和中国计算机学会自然语言处理专委会" + "承办,已连续举办4届,成为全球最热门的中文NLP赛事之一。"}, + &results); + std::cout << results << std::endl; return 0; } diff --git a/examples/text/information_extraction/ernie/cpp/uie.cc b/examples/text/information_extraction/ernie/cpp/uie.cc index b4be7788932..cc2be7c97ca 100644 --- a/examples/text/information_extraction/ernie/cpp/uie.cc +++ b/examples/text/information_extraction/ernie/cpp/uie.cc @@ -17,6 +17,7 @@ #include #include #include +#include #include "utils/utf8.h" // faster_tokenizer helper funciton @@ -63,10 +64,72 @@ static void CharToByteOffsetMap(const std::string& seq, offset_mapping->push_back(index); } +static std::ostream& PrintResult(std::ostream& os, const UIEResult& result, + int tab_size) { + constexpr int TAB_OFFSET = 4; + // Print text + for (int i = 0; i < tab_size; ++i) { + os << " "; + } + os << "text: " << result.text_ << "\n"; + + // Print probability + for (int i = 0; i < tab_size; ++i) { + os << " "; + } + os << "probability: " << result.probability_ << "\n"; + + // Print start + for (int i = 0; i < tab_size; ++i) { + os << " "; + } + os << "start: " << result.start_ << "\n"; + + // Print end + for (int i = 0; i < tab_size; ++i) { + os << " "; + } + os << "end: " << result.end_ << "\n"; + + // Print relation + if (result.relation_.size() > 0) { + for (int i = 0; i < tab_size; ++i) { + os << " "; + } + os << "relation:\n"; + for (auto&& curr_relation : result.relation_) { + for (int i = 0; i < tab_size + TAB_OFFSET; ++i) { + os << " "; + } + os << curr_relation.first << ":\n"; + for (int i = 0; i < curr_relation.second.size(); ++i) { + PrintResult(os, curr_relation.second[i], + tab_size + TAB_OFFSET + TAB_OFFSET); + } + } + } + os << "\n"; + return os; +} + std::ostream& operator<<(std::ostream& os, const UIEResult& result) { - os << "text = " << result.text_ << "\nprobability = " << result.probability_ - << "\nstart = " << result.start_ << "\nend = " << result.end_; - os << std::endl; + return PrintResult(os, result, 0); +} + +std::ostream& operator<<( + std::ostream& os, + const std::vector>>& + results) { + os << "The result:\n"; + for (int i = 0; i < results.size(); ++i) { + for (auto&& curr_result : results[i]) { + os << curr_result.first << ": \n"; + for (auto&& uie_result : curr_result.second) { + PrintResult(os, uie_result, 4); + } + } + os << std::endl; + } return os; } @@ -88,7 +151,7 @@ Schema::Schema(const std::vector& schema_list, } Schema::Schema( - const std::unordered_map>& schema_map, + const std::unordered_map>& schema_map, const std::string& name) { CreateRoot(name); for (auto& schema_item : schema_map) { @@ -114,7 +177,7 @@ UIEModel::UIEModel(const std::string& model_file, UIEModel::UIEModel( const std::string& model_file, const std::string& params_file, const std::string& vocab_file, float position_prob, size_t max_length, - const std::unordered_map>& schema) + const std::unordered_map>& schema) : max_length_(max_length), position_prob_(position_prob), tokenizer_(vocab_file) { @@ -131,7 +194,7 @@ void UIEModel::SetSchema(const std::vector& schema) { } void UIEModel::SetSchema( - const std::unordered_map>& schema) { + const std::unordered_map>& schema) { schema_ = fastdeploy::utils::make_unique(schema); } @@ -142,7 +205,8 @@ void UIEModel::AutoSplitter( size_t cnt_org = 0; size_t cnt_short = 0; for (auto& text : texts) { - auto text_len = text.length(); + auto text_len = faster_tokenizer::utils::GetUnicodeLenFromUTF8( + text.c_str(), text.length()); if (text_len <= max_length) { short_texts->push_back(text); if (input_mapping->count(cnt_org) == 0) { @@ -152,12 +216,17 @@ void UIEModel::AutoSplitter( } cnt_short += 1; } else { + std::vector offset_mapping; + CharToByteOffsetMap(text, &offset_mapping); for (size_t start = 0; start < text_len; start += max_length) { size_t end = start + max_length; if (end > text_len) { end = text_len; } - short_texts->emplace_back(text.data() + start, end - start); + auto unicode_start = offset_mapping[start]; + auto unicode_end = offset_mapping[end]; + short_texts->emplace_back(text.data() + unicode_start, + unicode_end - unicode_start); } auto short_idx = cnt_short; cnt_short += text_len / max_length; @@ -391,7 +460,6 @@ void UIEModel::PredictUIEInput(const std::vector& input_texts, // 2. Tokenize the short texts and short prompts std::vector encodings; tokenizer_.EncodeBatchStrings(text_pair_input, &encodings); - // 3. Construct the input vector tensor // 3.1 Convert encodings to input_ids, token_type_ids, position_ids, attn_mask std::vector input_ids, token_type_ids, position_ids, attn_mask; @@ -461,8 +529,9 @@ void UIEModel::Predict( for (auto& node : schema_->root_->children_) { nodes.push(node); } + results->resize(texts.size()); while (!nodes.empty()) { - auto& node = nodes.front(); + auto node = nodes.front(); nodes.pop(); std::vector> input_mapping; size_t idx = 0; @@ -498,7 +567,6 @@ void UIEModel::Predict( // 2. Predict from UIEInput std::vector> results_list; PredictUIEInput(input_texts, prompts, &results_list); - // 3. Postprocess std::vector> relations; relations.resize(texts.size()); @@ -511,7 +579,7 @@ void UIEModel::Predict( continue; } if (curr_result.count(node.name_) == 0) { - curr_result[node.name_] = std::move(results_list[idx]); + curr_result[node.name_] = results_list[idx]; } else { curr_result[node.name_].insert(curr_result[node.name_].end(), results_list[idx].begin(), @@ -534,8 +602,7 @@ void UIEModel::Predict( continue; } if (new_relations[i][j]->relation_.count(node.name_) == 0) { - new_relations[i][j]->relation_[node.name_] = - std::move(results_list[idx]); + new_relations[i][j]->relation_[node.name_] = results_list[idx]; } else { auto& curr_result = new_relations[i][j]->relation_[node.name_]; curr_result.insert(curr_result.end(), results_list[idx].begin(), @@ -554,20 +621,19 @@ void UIEModel::Predict( } } } - std::vector> prefix(texts.size()); for (int i = 0; i < input_mapping.size(); ++i) { auto&& input_mapping_item = input_mapping[i]; for (auto&& idx : input_mapping_item) { for (int j = 0; j < results_list[idx].size(); ++j) { - prefix[i].push_back(results_list[idx][j].text_ + "\u7684"); + auto prefix_str = results_list[idx][j].text_ + "\xe7\x9a\x84"; + prefix[i].push_back(prefix_str); } } } - for (auto& node_child : node.children_) { - node_child.relations_ = std::move(relations); - node_child.prefix_ = std::move(prefix); + node_child.relations_ = relations; + node_child.prefix_ = prefix; nodes.push(node_child); } } diff --git a/examples/text/information_extraction/ernie/cpp/uie.h b/examples/text/information_extraction/ernie/cpp/uie.h index 61ab0319bcb..4a6d2cd4116 100644 --- a/examples/text/information_extraction/ernie/cpp/uie.h +++ b/examples/text/information_extraction/ernie/cpp/uie.h @@ -36,6 +36,10 @@ struct UIEResult { }; std::ostream& operator<<(std::ostream& os, const UIEResult& result); +std::ostream& operator<<( + std::ostream& os, + const std::vector>>& + results); struct SchemaNode { std::string name_; @@ -43,7 +47,9 @@ struct SchemaNode { std::vector> relations_; std::vector children_; - explicit SchemaNode(const std::string& name) : name_(name) {} + explicit SchemaNode(const std::string& name, + const std::vector& children = {}) + : name_(name), children_(children) {} void AddChild(const std::string& schema) { children_.emplace_back(schema); } void AddChild(const std::string& schema, const std::vector& children) { @@ -53,14 +59,20 @@ struct SchemaNode { } children_.emplace_back(schema_node); } + void AddChild(const std::string& schema, + const std::vector& children) { + SchemaNode schema_node(schema); + schema_node.children_ = children; + children_.emplace_back(schema_node); + } }; struct Schema { explicit Schema(const std::string& schema, const std::string& name = "root"); explicit Schema(const std::vector& schema_list, const std::string& name = "root"); - explicit Schema(const std::unordered_map< - std::string, std::vector>& schema_map, + explicit Schema(const std::unordered_map>& schema_map, const std::string& name = "root"); private: @@ -77,10 +89,10 @@ struct UIEModel { UIEModel( const std::string& model_file, const std::string& params_file, const std::string& vocab_file, float position_prob, size_t max_length, - const std::unordered_map>& schema); + const std::unordered_map>& schema); void SetSchema(const std::vector& schema); void SetSchema( - const std::unordered_map>& schema); + const std::unordered_map>& schema); void PredictUIEInput(const std::vector& input_texts, const std::vector& prompts, From 52e7dc5de936a5664fe7dedc95aa2bf36431f94a Mon Sep 17 00:00:00 2001 From: zhoushunjie Date: Mon, 22 Aug 2022 21:57:31 +0800 Subject: [PATCH 07/17] Fix uie unicode bug --- .../information_extraction/ernie/cpp/uie.cc | 24 ++++++++++++------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/examples/text/information_extraction/ernie/cpp/uie.cc b/examples/text/information_extraction/ernie/cpp/uie.cc index cc2be7c97ca..a9cfe22af25 100644 --- a/examples/text/information_extraction/ernie/cpp/uie.cc +++ b/examples/text/information_extraction/ernie/cpp/uie.cc @@ -364,7 +364,7 @@ void UIEModel::AutoJoiner( for (auto&& short_result : *results) { if (short_result.size() == 0) { continue; - } else if (short_result[0].start_ == 0 && short_result[0].end_) { + } else if (short_result[0].start_ == 0 && short_result[0].end_ == 0) { is_cls_task = true; break; } else { @@ -435,13 +435,20 @@ void UIEModel::PredictUIEInput(const std::vector& input_texts, const std::vector& prompts, std::vector>* results) { // 1. Shortten the input texts and prompts - auto max_predict_len = - max_length_ - 3 - - std::max_element(prompts.begin(), prompts.end(), - [](const std::string& lhs, const std::string& rhs) { - return lhs.length() < rhs.length(); - }) - ->length(); + auto max_prompt_iter = std::max_element( + prompts.begin(), prompts.end(), + [](const std::string& lhs, const std::string& rhs) { + auto lhs_ulen = faster_tokenizer::utils::GetUnicodeLenFromUTF8( + lhs.c_str(), lhs.length()); + auto rhs_ulen = faster_tokenizer::utils::GetUnicodeLenFromUTF8( + rhs.c_str(), rhs.length()); + return lhs_ulen < rhs_ulen; + }); + + auto max_prompt_len = faster_tokenizer::utils::GetUnicodeLenFromUTF8( + max_prompt_iter->c_str(), max_prompt_iter->length()); + auto max_predict_len = max_length_ - 3 - max_prompt_len; + std::vector short_texts; std::unordered_map> input_mapping; AutoSplitter(input_texts, max_predict_len, &short_texts, &input_mapping); @@ -503,7 +510,6 @@ void UIEModel::PredictUIEInput(const std::vector& input_texts, // 5. Postprocess std::vector>> start_candidate_idx_prob, end_candidate_idx_prob; - GetCandidateIdx(start_prob, outputs[0].shape[0], outputs[0].shape[1], &start_candidate_idx_prob, position_prob_); GetCandidateIdx(end_prob, outputs[1].shape[0], outputs[1].shape[1], From a7a1cd43081514ac344d4502e90343b22f563826 Mon Sep 17 00:00:00 2001 From: zhoushunjie Date: Mon, 22 Aug 2022 22:00:04 +0800 Subject: [PATCH 08/17] rename information_extraction/ernie -> uie --- .../text/{information_extraction/ernie => uie}/cpp/CMakeLists.txt | 0 examples/text/{information_extraction/ernie => uie}/cpp/infer.cc | 0 examples/text/{information_extraction/ernie => uie}/cpp/uie.cc | 0 examples/text/{information_extraction/ernie => uie}/cpp/uie.h | 0 4 files changed, 0 insertions(+), 0 deletions(-) rename examples/text/{information_extraction/ernie => uie}/cpp/CMakeLists.txt (100%) rename examples/text/{information_extraction/ernie => uie}/cpp/infer.cc (100%) rename examples/text/{information_extraction/ernie => uie}/cpp/uie.cc (100%) rename examples/text/{information_extraction/ernie => uie}/cpp/uie.h (100%) diff --git a/examples/text/information_extraction/ernie/cpp/CMakeLists.txt b/examples/text/uie/cpp/CMakeLists.txt similarity index 100% rename from examples/text/information_extraction/ernie/cpp/CMakeLists.txt rename to examples/text/uie/cpp/CMakeLists.txt diff --git a/examples/text/information_extraction/ernie/cpp/infer.cc b/examples/text/uie/cpp/infer.cc similarity index 100% rename from examples/text/information_extraction/ernie/cpp/infer.cc rename to examples/text/uie/cpp/infer.cc diff --git a/examples/text/information_extraction/ernie/cpp/uie.cc b/examples/text/uie/cpp/uie.cc similarity index 100% rename from examples/text/information_extraction/ernie/cpp/uie.cc rename to examples/text/uie/cpp/uie.cc diff --git a/examples/text/information_extraction/ernie/cpp/uie.h b/examples/text/uie/cpp/uie.h similarity index 100% rename from examples/text/information_extraction/ernie/cpp/uie.h rename to examples/text/uie/cpp/uie.h From 3f94c2a4aac8810311b36135a19781ede1d95b6d Mon Sep 17 00:00:00 2001 From: zhoushunjie Date: Mon, 22 Aug 2022 22:24:12 +0800 Subject: [PATCH 09/17] Add more uie task --- examples/text/uie/cpp/infer.cc | 37 +++++++++++++++++++++++++++++++--- examples/text/uie/cpp/uie.cc | 20 +++++++++--------- 2 files changed, 45 insertions(+), 12 deletions(-) diff --git a/examples/text/uie/cpp/infer.cc b/examples/text/uie/cpp/infer.cc index a8d373850ef..6abe5663ee1 100644 --- a/examples/text/uie/cpp/infer.cc +++ b/examples/text/uie/cpp/infer.cc @@ -28,22 +28,53 @@ int main() { "uie-base/vocab.txt", 0.5, 128, {"时间", "选手", "赛事名称"}); fastdeploy::FDINFO << "After init predictor" << std::endl; std::vector>> results; + // Named Entity Recognition predictor.Predict({"2月8日上午北京冬奥会自由式滑雪女子大跳台决赛中中国选手谷" "爱凌以188.25分获得金牌!"}, &results); std::cout << results << std::endl; + results.clear(); - // schema for relation extraction - // schema = {'竞赛名称': ['主办方', '承办方', '已举办次数']} + // Relation Extraction predictor.SetSchema({{"竞赛名称", {SchemaNode("主办方"), SchemaNode("承办方"), SchemaNode("已举办次数")}}}); - results.clear(); predictor.Predict( {"2022语言与智能技术竞赛由中国中文信息学会和中国计算机学会联合主办,百度" "公司、中国中文信息学会评测工作委员会和中国计算机学会自然语言处理专委会" "承办,已连续举办4届,成为全球最热门的中文NLP赛事之一。"}, &results); std::cout << results << std::endl; + results.clear(); + + // Event Extraction + predictor.SetSchema({{"地震触发词", + {SchemaNode("地震强度"), SchemaNode("时间"), + SchemaNode("震中位置"), SchemaNode("震源深度")}}}); + predictor.Predict( + {"中国地震台网正式测定:5月16日06时08分在云南临沧市凤庆县(北纬24." + "34度,东经99.98度)发生3.5级地震,震源深度10千米。"}, + &results); + std::cout << results << std::endl; + results.clear(); + + // Opinion Extraction + predictor.SetSchema( + {{"评价维度", + {SchemaNode("观点词"), SchemaNode("情感倾向[正向,负向]")}}}); + predictor.Predict( + {"店面干净,很清静,服务员服务热情,性价比很高,发现收银台有排队"}, + &results); + std::cout << results << std::endl; + results.clear(); + + // Sequence classification + predictor.SetSchema({"情感倾向[正向,负向]"}); + predictor.Predict({"这个产品用起来真的很流畅,我非常喜欢"}, &results); + std::cout << results << std::endl; + results.clear(); + + // Cross task extraction + return 0; } diff --git a/examples/text/uie/cpp/uie.cc b/examples/text/uie/cpp/uie.cc index a9cfe22af25..32d19860fbf 100644 --- a/examples/text/uie/cpp/uie.cc +++ b/examples/text/uie/cpp/uie.cc @@ -79,17 +79,19 @@ static std::ostream& PrintResult(std::ostream& os, const UIEResult& result, } os << "probability: " << result.probability_ << "\n"; - // Print start - for (int i = 0; i < tab_size; ++i) { - os << " "; - } - os << "start: " << result.start_ << "\n"; + if (result.start_ != 0 || result.end_ != 0) { + // Print start + for (int i = 0; i < tab_size; ++i) { + os << " "; + } + os << "start: " << result.start_ << "\n"; - // Print end - for (int i = 0; i < tab_size; ++i) { - os << " "; + // Print end + for (int i = 0; i < tab_size; ++i) { + os << " "; + } + os << "end: " << result.end_ << "\n"; } - os << "end: " << result.end_ << "\n"; // Print relation if (result.relation_.size() > 0) { From cf8df59681cfde274a1d3e6d16dd30fefbb7a294 Mon Sep 17 00:00:00 2001 From: zhoushunjie Date: Tue, 23 Aug 2022 10:59:02 +0800 Subject: [PATCH 10/17] Add cross task extraction --- examples/text/uie/cpp/infer.cc | 10 ++++++++++ examples/text/uie/cpp/uie.h | 1 + 2 files changed, 11 insertions(+) diff --git a/examples/text/uie/cpp/infer.cc b/examples/text/uie/cpp/infer.cc index 6abe5663ee1..10f0bcafeb5 100644 --- a/examples/text/uie/cpp/infer.cc +++ b/examples/text/uie/cpp/infer.cc @@ -76,5 +76,15 @@ int main() { // Cross task extraction + predictor.SetSchema({{"法院", {}}, + {"原告", {SchemaNode("委托代理人")}}, + {"被告", {SchemaNode("委托代理人")}}}); + predictor.Predict({"北京市海淀区人民法院\n民事判决书\n(199x)" + "建初字第xxx号\n原告:张三。\n委托代理人李四,北京市 " + "A律师事务所律师。\n被告:B公司,法定代表人王五,开发公司" + "总经理。\n委托代理人赵六,北京市 C律师事务所律师。"}, + &results); + std::cout << results << std::endl; + results.clear(); return 0; } diff --git a/examples/text/uie/cpp/uie.h b/examples/text/uie/cpp/uie.h index 4a6d2cd4116..f1e4328b520 100644 --- a/examples/text/uie/cpp/uie.h +++ b/examples/text/uie/cpp/uie.h @@ -51,6 +51,7 @@ struct SchemaNode { const std::vector& children = {}) : name_(name), children_(children) {} void AddChild(const std::string& schema) { children_.emplace_back(schema); } + void AddChild(const SchemaNode& schema) { children_.push_back(schema); } void AddChild(const std::string& schema, const std::vector& children) { SchemaNode schema_node(schema); From 134e7d35b2218961f66b8f1917931e0e48fb0b49 Mon Sep 17 00:00:00 2001 From: zhoushunjie Date: Tue, 23 Aug 2022 20:23:17 +0800 Subject: [PATCH 11/17] use CharToBytesOffsetConverter --- examples/text/uie/cpp/uie.cc | 50 +++++++++++++++--------------------- 1 file changed, 20 insertions(+), 30 deletions(-) diff --git a/examples/text/uie/cpp/uie.cc b/examples/text/uie/cpp/uie.cc index 32d19860fbf..55fd53a7c8b 100644 --- a/examples/text/uie/cpp/uie.cc +++ b/examples/text/uie/cpp/uie.cc @@ -19,7 +19,8 @@ #include #include -#include "utils/utf8.h" // faster_tokenizer helper funciton +#include "pretokenizers/pretokenizer.h" // faster_tokenizer helper funciton +#include "utils/utf8.h" // faster_tokenizer helper funciton static std::string DBC2SBC(const std::string& content) { std::string result; @@ -49,21 +50,6 @@ static std::string DBC2SBC(const std::string& content) { return result; } -// Will remove to faster_tokenizer utils -static void CharToByteOffsetMap(const std::string& seq, - std::vector* offset_mapping) { - std::wstring_convert, char32_t> conv; - std::u32string u32seq = conv.from_bytes(seq); - uint32_t index = 0; - offset_mapping->reserve(u32seq.length() * 4); - for (int i = 0; i < u32seq.length(); ++i) { - offset_mapping->push_back(index); - auto utf8_len = faster_tokenizer::utils::GetUTF8CharLen(u32seq[i]); - index += utf8_len; - } - offset_mapping->push_back(index); -} - static std::ostream& PrintResult(std::ostream& os, const UIEResult& result, int tab_size) { constexpr int TAB_OFFSET = 4; @@ -218,17 +204,17 @@ void UIEModel::AutoSplitter( } cnt_short += 1; } else { - std::vector offset_mapping; - CharToByteOffsetMap(text, &offset_mapping); + faster_tokenizer::pretokenizers::CharToBytesOffsetConverter converter( + text); for (size_t start = 0; start < text_len; start += max_length) { size_t end = start + max_length; if (end > text_len) { end = text_len; } - auto unicode_start = offset_mapping[start]; - auto unicode_end = offset_mapping[end]; - short_texts->emplace_back(text.data() + unicode_start, - unicode_end - unicode_start); + faster_tokenizer::core::Offset byte_offset; + converter.convert({start, end}, &byte_offset); + short_texts->emplace_back(text.data() + byte_offset.first, + byte_offset.second - byte_offset.first); } auto short_idx = cnt_short; cnt_short += text_len / max_length; @@ -338,18 +324,22 @@ void UIEModel::ConvertSpanToUIEResult( std::string span_text; std::vector offset_mapping; if (span_idxs[i][j].is_prompt_) { - CharToByteOffsetMap(prompt, &offset_mapping); - auto byte_start = offset_mapping[start]; - auto byte_end = offset_mapping[end]; - span_text = prompt.substr(byte_start, byte_end - byte_start); + faster_tokenizer::pretokenizers::CharToBytesOffsetConverter converter( + prompt); + faster_tokenizer::core::Offset byte_offset; + converter.convert({start, end}, &byte_offset); + span_text = prompt.substr(byte_offset.first, + byte_offset.second - byte_offset.first); // Indicate cls task start = 0; end = 0; } else { - CharToByteOffsetMap(text, &offset_mapping); - auto byte_start = offset_mapping[start]; - auto byte_end = offset_mapping[end]; - span_text = text.substr(byte_start, byte_end - byte_start); + faster_tokenizer::pretokenizers::CharToBytesOffsetConverter converter( + text); + faster_tokenizer::core::Offset byte_offset; + converter.convert({start, end}, &byte_offset); + span_text = text.substr(byte_offset.first, + byte_offset.second - byte_offset.first); } result_list.emplace_back(start, end, probs[i][j], span_text); } From b933b495cfecc824b38d1728d508bcba007be10a Mon Sep 17 00:00:00 2001 From: zhoushunjie Date: Tue, 23 Aug 2022 22:35:17 +0800 Subject: [PATCH 12/17] Add faster_tokenizer dir --- FastDeploy.cmake.in | 1 + examples/text/uie/cpp/infer.cc | 2 +- examples/text/uie/cpp/uie.cc | 4 ++-- examples/text/uie/cpp/uie.h | 2 +- 4 files changed, 5 insertions(+), 4 deletions(-) diff --git a/FastDeploy.cmake.in b/FastDeploy.cmake.in index ccd1039be29..b22e40c44b1 100644 --- a/FastDeploy.cmake.in +++ b/FastDeploy.cmake.in @@ -98,6 +98,7 @@ if (ENABLE_TEXT) find_library(FASTER_TOKENIZER_LIB core_tokenizers ${CMAKE_CURRENT_LIST_DIR}/third_libs/install/faster_tokenizer/lib NO_DEFAULT_PATH) list(APPEND FASTDEPLOY_LIBS ${FASTER_TOKENIZER_LIB}) list(APPEND FASTDEPLOY_INCS ${CMAKE_CURRENT_LIST_DIR}/third_libs/install/faster_tokenizer/include) + list(APPEND FASTDEPLOY_INCS ${CMAKE_CURRENT_LIST_DIR}/third_libs/install/faster_tokenizer/include/faster_tokenizer) list(APPEND FASTDEPLOY_INCS ${CMAKE_CURRENT_LIST_DIR}/third_libs/install/faster_tokenizer/third_party/include) endif() diff --git a/examples/text/uie/cpp/infer.cc b/examples/text/uie/cpp/infer.cc index 10f0bcafeb5..3e2ddb54822 100644 --- a/examples/text/uie/cpp/infer.cc +++ b/examples/text/uie/cpp/infer.cc @@ -17,7 +17,7 @@ #include "fastdeploy/function/reduce.h" #include "fastdeploy/function/softmax.h" #include "fastdeploy/text.h" -#include "tokenizers/ernie_faster_tokenizer.h" +#include "faster_tokenizer/tokenizers/ernie_faster_tokenizer.h" #include "uie.h" using namespace paddlenlp; diff --git a/examples/text/uie/cpp/uie.cc b/examples/text/uie/cpp/uie.cc index 55fd53a7c8b..624ce4829a7 100644 --- a/examples/text/uie/cpp/uie.cc +++ b/examples/text/uie/cpp/uie.cc @@ -19,8 +19,8 @@ #include #include -#include "pretokenizers/pretokenizer.h" // faster_tokenizer helper funciton -#include "utils/utf8.h" // faster_tokenizer helper funciton +#include "faster_tokenizer/pretokenizers/pretokenizer.h" +#include "faster_tokenizer/utils/utf8.h" static std::string DBC2SBC(const std::string& content) { std::string result; diff --git a/examples/text/uie/cpp/uie.h b/examples/text/uie/cpp/uie.h index f1e4328b520..b636b4b8be3 100644 --- a/examples/text/uie/cpp/uie.h +++ b/examples/text/uie/cpp/uie.h @@ -20,7 +20,7 @@ #include #include "fastdeploy/fastdeploy_model.h" #include "fastdeploy/utils/unique_ptr.h" -#include "tokenizers/ernie_faster_tokenizer.h" +#include "faster_tokenizer/tokenizers/ernie_faster_tokenizer.h" using namespace paddlenlp; From 7263c249c0232f399b7c047a0a1d0b2a30fe7043 Mon Sep 17 00:00:00 2001 From: zhoushunjie Date: Wed, 24 Aug 2022 16:03:40 +0800 Subject: [PATCH 13/17] Add RuntimeOption args --- examples/text/uie/cpp/CMakeLists.txt | 4 ++-- examples/text/uie/cpp/README.md | 32 +++++++++++++++++++++++++++ examples/text/uie/cpp/infer.cc | 33 ++++++++++++++++++++++++---- examples/text/uie/cpp/uie.cc | 12 ++++++++-- examples/text/uie/cpp/uie.h | 15 +++++++++---- 5 files changed, 84 insertions(+), 12 deletions(-) create mode 100644 examples/text/uie/cpp/README.md diff --git a/examples/text/uie/cpp/CMakeLists.txt b/examples/text/uie/cpp/CMakeLists.txt index 6d6faad76c2..80731eda452 100644 --- a/examples/text/uie/cpp/CMakeLists.txt +++ b/examples/text/uie/cpp/CMakeLists.txt @@ -21,5 +21,5 @@ include(${FASTDEPLOY_INSTALL_DIR}/FastDeploy.cmake) include_directories(${FASTDEPLOY_INCS}) -add_executable(infer_ernie_demo ${PROJECT_SOURCE_DIR}/infer.cc ${PROJECT_SOURCE_DIR}/uie.cc) -target_link_libraries(infer_ernie_demo ${FASTDEPLOY_LIBS}) +add_executable(infer_demo ${PROJECT_SOURCE_DIR}/infer.cc ${PROJECT_SOURCE_DIR}/uie.cc) +target_link_libraries(infer_demo ${FASTDEPLOY_LIBS}) diff --git a/examples/text/uie/cpp/README.md b/examples/text/uie/cpp/README.md new file mode 100644 index 00000000000..cec6d679181 --- /dev/null +++ b/examples/text/uie/cpp/README.md @@ -0,0 +1,32 @@ +# UIE C++部署示例 + +本目录下提供`infer.cc`快速完成UIE模型在CPU/GPU,以及GPU上通过TensorRT加速部署的示例。 + +在部署前,需确认以下两个步骤 + +- 1. 软硬件环境满足要求,参考[FastDeploy环境要求](../../../../docs/quick_start/requirements.md) +- 2. 根据开发环境,下载预编译部署库和samples代码,参考[FastDeploy预编译库](../../../../docs/compile/prebuilt_libraries.md) + +以Linux上uie-base模型推理为例,在本目录执行如下命令即可完成编译测试。 + +``` +#下载SDK,编译模型examples代码(SDK中包含了examples代码) +wget https://bj.bcebos.com/paddlehub/fastdeploy/libs/0.2.0/fastdeploy-linux-x64-gpu-0.2.0.tgz +tar xvf fastdeploy-linux-x64-gpu-0.2.0.tgz +cd fastdeploy-linux-x64-gpu-0.2.0/examples/text/uie/cpp +mkdir build +cd build +cmake .. -DFASTDEPLOY_INSTALL_DIR=${PWD}/../../../../../fastdeploy-linux-x64-gpu-0.2.0 +make -j + +# 下载uie-base模型以及词表 +wget https://bj.bcebos.com/fastdeploy/models/uie/uie-base.tgz +tar -xvfz uie-base.tgz + + +# CPU 推理 +./infer_demo uie-base 0 + +# GPU 推理 +./infer_demo uie-base 1 +``` diff --git a/examples/text/uie/cpp/infer.cc b/examples/text/uie/cpp/infer.cc index 3e2ddb54822..70d6f3518d1 100644 --- a/examples/text/uie/cpp/infer.cc +++ b/examples/text/uie/cpp/infer.cc @@ -22,10 +22,35 @@ using namespace paddlenlp; -int main() { - auto predictor = - UIEModel("uie-base/inference.pdmodel", "uie-base/inference.pdiparams", - "uie-base/vocab.txt", 0.5, 128, {"时间", "选手", "赛事名称"}); +#ifdef WIN32 +const char sep = '\\'; +#else +const char sep = '/'; +#endif + +int main(int argc, char* argv[]) { + if (argc < 3) { + std::cout << "Usage: infer_demo path/to/model run_option, " + "e.g ./infer_demo uie-base 0" + << std::endl; + std::cout << "The data type of run_option is int, 0: run with cpu; 1: run " + "with gpu." + << std::endl; + return -1; + } + auto option = fastdeploy::RuntimeOption(); + if (std::atoi(argv[2]) == 0) { + option.UseCpu(); + } else { + option.UseGpu(); + } + std::string model_dir(argv[1]); + std::string model_path = model_dir + sep + "inference.pdmodel"; + std::string param_path = model_dir + sep + "inference.pdiparams"; + std::string vocab_path = model_dir + sep + "vocab.txt"; + + auto predictor = UIEModel(model_path, param_path, vocab_path, 0.5, 128, + {"时间", "选手", "赛事名称"}, option); fastdeploy::FDINFO << "After init predictor" << std::endl; std::vector>> results; // Named Entity Recognition diff --git a/examples/text/uie/cpp/uie.cc b/examples/text/uie/cpp/uie.cc index 624ce4829a7..e9f124ba520 100644 --- a/examples/text/uie/cpp/uie.cc +++ b/examples/text/uie/cpp/uie.cc @@ -150,10 +150,14 @@ Schema::Schema( UIEModel::UIEModel(const std::string& model_file, const std::string& params_file, const std::string& vocab_file, float position_prob, - size_t max_length, const std::vector& schema) + size_t max_length, const std::vector& schema, + const fastdeploy::RuntimeOption& custom_option, + const fastdeploy::Frontend& model_format) : max_length_(max_length), position_prob_(position_prob), tokenizer_(vocab_file) { + runtime_option_ = custom_option; + runtime_option_.model_format = model_format; runtime_option_.SetModelPath(model_file, params_file); runtime_.Init(runtime_option_); SetSchema(schema); @@ -165,10 +169,14 @@ UIEModel::UIEModel(const std::string& model_file, UIEModel::UIEModel( const std::string& model_file, const std::string& params_file, const std::string& vocab_file, float position_prob, size_t max_length, - const std::unordered_map>& schema) + const std::unordered_map>& schema, + const fastdeploy::RuntimeOption& custom_option, + const fastdeploy::Frontend& model_format) : max_length_(max_length), position_prob_(position_prob), tokenizer_(vocab_file) { + runtime_option_ = custom_option; + runtime_option_.model_format = model_format; runtime_option_.SetModelPath(model_file, params_file); runtime_.Init(runtime_option_); SetSchema(schema); diff --git a/examples/text/uie/cpp/uie.h b/examples/text/uie/cpp/uie.h index b636b4b8be3..5894ae1d63b 100644 --- a/examples/text/uie/cpp/uie.h +++ b/examples/text/uie/cpp/uie.h @@ -84,13 +84,20 @@ struct Schema { struct UIEModel { public: - UIEModel(const std::string& model_file, const std::string& params_file, - const std::string& vocab_file, float position_prob, - size_t max_length, const std::vector& schema); UIEModel( const std::string& model_file, const std::string& params_file, const std::string& vocab_file, float position_prob, size_t max_length, - const std::unordered_map>& schema); + const std::vector& schema, + const fastdeploy::RuntimeOption& custom_option = + fastdeploy::RuntimeOption(), + const fastdeploy::Frontend& model_format = fastdeploy::Frontend::PADDLE); + UIEModel( + const std::string& model_file, const std::string& params_file, + const std::string& vocab_file, float position_prob, size_t max_length, + const std::unordered_map>& schema, + const fastdeploy::RuntimeOption& custom_option = + fastdeploy::RuntimeOption(), + const fastdeploy::Frontend& model_format = fastdeploy::Frontend::PADDLE); void SetSchema(const std::vector& schema); void SetSchema( const std::unordered_map>& schema); From 95369f17b6278967de7f4954e29a842419c8bf3f Mon Sep 17 00:00:00 2001 From: zhoushunjie Date: Wed, 24 Aug 2022 16:06:29 +0800 Subject: [PATCH 14/17] Add todo comments --- FastDeploy.cmake.in | 1 + external/faster_tokenizer.cmake | 1 + 2 files changed, 2 insertions(+) diff --git a/FastDeploy.cmake.in b/FastDeploy.cmake.in index b22e40c44b1..3ccd22aa367 100644 --- a/FastDeploy.cmake.in +++ b/FastDeploy.cmake.in @@ -98,6 +98,7 @@ if (ENABLE_TEXT) find_library(FASTER_TOKENIZER_LIB core_tokenizers ${CMAKE_CURRENT_LIST_DIR}/third_libs/install/faster_tokenizer/lib NO_DEFAULT_PATH) list(APPEND FASTDEPLOY_LIBS ${FASTER_TOKENIZER_LIB}) list(APPEND FASTDEPLOY_INCS ${CMAKE_CURRENT_LIST_DIR}/third_libs/install/faster_tokenizer/include) + # TODO (zhoushunjie): Will remove it later. list(APPEND FASTDEPLOY_INCS ${CMAKE_CURRENT_LIST_DIR}/third_libs/install/faster_tokenizer/include/faster_tokenizer) list(APPEND FASTDEPLOY_INCS ${CMAKE_CURRENT_LIST_DIR}/third_libs/install/faster_tokenizer/third_party/include) endif() diff --git a/external/faster_tokenizer.cmake b/external/faster_tokenizer.cmake index fabc33db581..c6e77adfe83 100644 --- a/external/faster_tokenizer.cmake +++ b/external/faster_tokenizer.cmake @@ -23,6 +23,7 @@ set(FASTERTOKENIZER_INSTALL_DIR ${THIRD_PARTY_PATH}/install/faster_tokenizer) set(FASTERTOKENIZER_INC_DIR "${FASTERTOKENIZER_INSTALL_DIR}/include" "${FASTERTOKENIZER_INSTALL_DIR}/third_party/include" + "${FASTERTOKENIZER_INSTALL_DIR}/third_party/include/faster_tokenizer" # TODO (zhoushunjie): Will remove it later. CACHE PATH "faster_tokenizer include directory." FORCE) set(FASTERTOKENIZER_LIB_DIR "${FASTERTOKENIZER_INSTALL_DIR}/lib/" From c25926eae4294ba1a2f11d82927b26277290c840 Mon Sep 17 00:00:00 2001 From: zhoushunjie Date: Wed, 24 Aug 2022 16:15:20 +0800 Subject: [PATCH 15/17] Add some readme --- examples/text/uie/cpp/README.md | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/examples/text/uie/cpp/README.md b/examples/text/uie/cpp/README.md index cec6d679181..3e6fe859a42 100644 --- a/examples/text/uie/cpp/README.md +++ b/examples/text/uie/cpp/README.md @@ -1,6 +1,6 @@ -# UIE C++部署示例 +# 通用信息抽取 UIE C++部署示例 -本目录下提供`infer.cc`快速完成UIE模型在CPU/GPU,以及GPU上通过TensorRT加速部署的示例。 +本目录下提供`infer.cc`快速完成[UIE模型](https://github.com/PaddlePaddle/PaddleNLP/tree/develop/model_zoo/uie)在CPU/GPU,以及GPU上通过TensorRT加速部署的示例。 在部署前,需确认以下两个步骤 @@ -30,3 +30,6 @@ tar -xvfz uie-base.tgz # GPU 推理 ./infer_demo uie-base 1 ``` + +## 模型获取 +UIE 模型介绍可以参考https://github.com/PaddlePaddle/PaddleNLP/tree/develop/model_zoo/uie。其中,在完成训练后,需要将训练后的模型导出成推理模型。该步骤可参考该文档完成导出:https://github.com/PaddlePaddle/PaddleNLP/tree/develop/model_zoo/uie#%E6%A8%A1%E5%9E%8B%E9%83%A8%E7%BD%B2 。 From 342c1979f5ff1a620d68cc1305dae6d0fa1ef9fc Mon Sep 17 00:00:00 2001 From: zhoushunjie Date: Wed, 24 Aug 2022 16:38:28 +0800 Subject: [PATCH 16/17] fix readme --- examples/text/uie/cpp/README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/text/uie/cpp/README.md b/examples/text/uie/cpp/README.md index 3e6fe859a42..94a6aa7970a 100644 --- a/examples/text/uie/cpp/README.md +++ b/examples/text/uie/cpp/README.md @@ -1,6 +1,6 @@ # 通用信息抽取 UIE C++部署示例 -本目录下提供`infer.cc`快速完成[UIE模型](https://github.com/PaddlePaddle/PaddleNLP/tree/develop/model_zoo/uie)在CPU/GPU,以及GPU上通过TensorRT加速部署的示例。 +本目录下提供`infer.cc`快速完成[UIE模型](https://github.com/PaddlePaddle/PaddleNLP/tree/develop/model_zoo/uie)在CPU/GPU的示例。 在部署前,需确认以下两个步骤 @@ -32,4 +32,4 @@ tar -xvfz uie-base.tgz ``` ## 模型获取 -UIE 模型介绍可以参考https://github.com/PaddlePaddle/PaddleNLP/tree/develop/model_zoo/uie。其中,在完成训练后,需要将训练后的模型导出成推理模型。该步骤可参考该文档完成导出:https://github.com/PaddlePaddle/PaddleNLP/tree/develop/model_zoo/uie#%E6%A8%A1%E5%9E%8B%E9%83%A8%E7%BD%B2 。 +UIE 模型介绍可以参考https://github.com/PaddlePaddle/PaddleNLP/tree/develop/model_zoo/uie 。其中,在完成训练后,需要将训练后的模型导出成推理模型。该步骤可参考该文档完成导出:https://github.com/PaddlePaddle/PaddleNLP/tree/develop/model_zoo/uie#%E6%A8%A1%E5%9E%8B%E9%83%A8%E7%BD%B2 。 From 30c878454b2ba708f773c4b7393e43732341c5e9 Mon Sep 17 00:00:00 2001 From: zhoushunjie Date: Wed, 24 Aug 2022 17:45:15 +0800 Subject: [PATCH 17/17] Fix readme --- examples/text/uie/cpp/README.md | 22 +++++++++++++++++----- 1 file changed, 17 insertions(+), 5 deletions(-) diff --git a/examples/text/uie/cpp/README.md b/examples/text/uie/cpp/README.md index 94a6aa7970a..c943b5042be 100644 --- a/examples/text/uie/cpp/README.md +++ b/examples/text/uie/cpp/README.md @@ -10,13 +10,25 @@ 以Linux上uie-base模型推理为例,在本目录执行如下命令即可完成编译测试。 ``` -#下载SDK,编译模型examples代码(SDK中包含了examples代码) -wget https://bj.bcebos.com/paddlehub/fastdeploy/libs/0.2.0/fastdeploy-linux-x64-gpu-0.2.0.tgz -tar xvf fastdeploy-linux-x64-gpu-0.2.0.tgz -cd fastdeploy-linux-x64-gpu-0.2.0/examples/text/uie/cpp +# UIE目前还未发布,当前需开发者自行编译FastDeploy,通过如下脚本编译得到部署库fastdeploy-linux-x64-dev +git clone https://github.com/PaddlePaddle/FastDeploy.git +cd FastDeploy +mkdir build && cd build +cmake .. -DENABLE_ORT_BACKEND=ON \ + -DENABLE_VISION=ON \ + -DENABLE_PADDLE_BACKEND=ON \ + -DENABLE_TEXT=ON \ + -DWITH_GPU=ON \ + -DCMAKE_INSTALL_PREFIX=${PWD}/fastdeploy-linux-x64-gpu-dev + +make -j8 +make install + +# 编译模型examples代码(SDK中包含了examples代码) +cd ../examples/text/uie/cpp mkdir build cd build -cmake .. -DFASTDEPLOY_INSTALL_DIR=${PWD}/../../../../../fastdeploy-linux-x64-gpu-0.2.0 +cmake .. -DFASTDEPLOY_INSTALL_DIR=${PWD}/../../../../../build/fastdeploy-linux-x64-gpu-dev make -j # 下载uie-base模型以及词表