Skip to content

Commit 2390da3

Browse files
committed
feat(contextual_translation): weight and re-order phrases by context
1 parent 6ae34de commit 2390da3

6 files changed

+126
-7
lines changed
+60
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
#include <algorithm>
2+
#include <iterator>
3+
#include <rime/gear/contextual_translation.h>
4+
#include <rime/gear/translator_commons.h>
5+
6+
namespace rime {
7+
8+
const int kContextualSearchLimit = 32;
9+
10+
bool ContextualTranslation::Replenish() {
11+
vector<of<Phrase>> queue;
12+
size_t end_pos = 0;
13+
while (!translation_->exhausted() &&
14+
cache_.size() + queue.size() < kContextualSearchLimit) {
15+
auto cand = translation_->Peek();
16+
DLOG(INFO) << cand->text() << " cache/queue: "
17+
<< cache_.size() << "/" << queue.size();
18+
if (cand->type() == "phrase" || cand->type() == "table") {
19+
if (end_pos != cand->end()) {
20+
end_pos = cand->end();
21+
AppendToCache(queue);
22+
}
23+
queue.push_back(Evaluate(As<Phrase>(cand)));
24+
} else {
25+
AppendToCache(queue);
26+
cache_.push_back(cand);
27+
}
28+
if (!translation_->Next()) {
29+
break;
30+
}
31+
}
32+
AppendToCache(queue);
33+
return !cache_.empty();
34+
}
35+
36+
an<Phrase> ContextualTranslation::Evaluate(an<Phrase> phrase) {
37+
auto sentence = New<Sentence>(phrase->language());
38+
sentence->Offset(phrase->start());
39+
bool is_rear = phrase->end() == input_.length();
40+
sentence->Extend(phrase->entry(), phrase->end(), is_rear, preceding_text_,
41+
grammar_);
42+
phrase->set_weight(sentence->weight());
43+
DLOG(INFO) << "contextual suggestion: " << phrase->text()
44+
<< " weight: " << phrase->weight();
45+
return phrase;
46+
}
47+
48+
static bool compare_by_weight_desc(const an<Phrase>& a, const an<Phrase>& b) {
49+
return a->weight() > b->weight();
50+
}
51+
52+
void ContextualTranslation::AppendToCache(vector<of<Phrase>>& queue) {
53+
if (queue.empty()) return;
54+
DLOG(INFO) << "appending to cache " << queue.size() << " candidates.";
55+
std::sort(queue.begin(), queue.end(), compare_by_weight_desc);
56+
std::copy(queue.begin(), queue.end(), std::back_inserter(cache_));
57+
queue.clear();
58+
}
59+
60+
} // namespace rime
+38
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
//
2+
// Copyright RIME Developers
3+
// Distributed under the BSD License
4+
//
5+
6+
#include <rime/common.h>
7+
#include <rime/translation.h>
8+
9+
namespace rime {
10+
11+
class Candidate;
12+
class Grammar;
13+
class Phrase;
14+
15+
class ContextualTranslation : public PrefetchTranslation {
16+
public:
17+
ContextualTranslation(an<Translation> translation,
18+
string input,
19+
string preceding_text,
20+
Grammar* grammar)
21+
: PrefetchTranslation(translation),
22+
input_(input),
23+
preceding_text_(preceding_text),
24+
grammar_(grammar) {}
25+
26+
protected:
27+
bool Replenish() override;
28+
29+
private:
30+
an<Phrase> Evaluate(an<Phrase> phrase);
31+
void AppendToCache(vector<of<Phrase>>& queue);
32+
33+
string input_;
34+
string preceding_text_;
35+
Grammar* grammar_;
36+
};
37+
38+
} // namespace rime

src/rime/gear/poet.h

+15
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,10 @@
1111
#define RIME_POET_H_
1212

1313
#include <rime/common.h>
14+
#include <rime/translation.h>
1415
#include <rime/dict/user_dictionary.h>
1516
#include <rime/gear/translator_commons.h>
17+
#include <rime/gear/contextual_translation.h>
1618

1719
namespace rime {
1820

@@ -39,6 +41,19 @@ class Poet {
3941
size_t total_length,
4042
const string& preceding_text);
4143

44+
template <class TranslatorT>
45+
an<Translation> ContextualWeighted(an<Translation> translation,
46+
const string& input,
47+
TranslatorT* translator) {
48+
if (!translator->contextual_suggestions() || !grammar_) {
49+
return translation;
50+
}
51+
return New<ContextualTranslation>(translation,
52+
input,
53+
translator->GetPrecedingText(),
54+
grammar_.get());
55+
}
56+
4257
private:
4358
const Language* language_;
4459
the<Grammar> grammar_;

src/rime/gear/script_translator.cc

+5-1
Original file line numberDiff line numberDiff line change
@@ -194,7 +194,11 @@ an<Translation> ScriptTranslator::Query(const string& input,
194194
enable_user_dict ? user_dict_.get() : NULL)) {
195195
return nullptr;
196196
}
197-
return New<DistinctTranslation>(result);
197+
auto deduped = New<DistinctTranslation>(result);
198+
if (contextual_suggestions_) {
199+
return poet_->ContextualWeighted(deduped, input, this);
200+
}
201+
return deduped;
198202
}
199203

200204
string ScriptTranslator::FormatPreedit(const string& preedit) {

src/rime/gear/table_translator.cc

+7-5
Original file line numberDiff line numberDiff line change
@@ -220,7 +220,8 @@ TableTranslator::TableTranslator(const Ticket& ticket)
220220
&max_phrase_length_);
221221
config->GetInt(name_space_ + "/max_homographs",
222222
&max_homographs_);
223-
if (enable_sentence_ || sentence_over_completion_) {
223+
if (enable_sentence_ || sentence_over_completion_ ||
224+
contextual_suggestions_) {
224225
poet_.reset(new Poet(language(), config, Poet::LeftAssociateCompare));
225226
}
226227
}
@@ -306,11 +307,12 @@ an<Translation> TableTranslator::Query(const string& input,
306307
translation = sentence + translation;
307308
}
308309
}
309-
if (translation) {
310-
translation = New<DistinctTranslation>(translation);
311-
}
312310
if (translation && translation->exhausted()) {
313-
translation.reset(); // discard futile translation
311+
return nullptr;
312+
}
313+
translation = New<DistinctTranslation>(translation);
314+
if (contextual_suggestions_) {
315+
return poet_->ContextualWeighted(translation, input, this);
314316
}
315317
return translation;
316318
}

src/rime/gear/translator_commons.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -91,8 +91,8 @@ class Phrase : public Candidate {
9191
void set_syllabifier(an<PhraseSyllabifier> syllabifier) {
9292
syllabifier_ = syllabifier;
9393
}
94-
9594
double weight() const { return entry_->weight; }
95+
void set_weight(double weight) { entry_->weight = weight; }
9696
Code& code() const { return entry_->code; }
9797
const DictEntry& entry() const { return *entry_; }
9898
const Language* language() const { return language_; }

0 commit comments

Comments
 (0)