feat(GODT-3121): adds KB suggestion scoring.
This commit is contained in:
parent
3309137b80
commit
b93c10ad47
|
@ -69,7 +69,7 @@ func NewShowMainWindowEvent() *StreamEvent {
|
|||
func NewRequestKnowledgeBaseSuggestionsEvent(suggestions kb.ArticleList) *StreamEvent {
|
||||
s := xslices.Map(
|
||||
suggestions,
|
||||
func(article kb.Article) *KnowledgeBaseSuggestion {
|
||||
func(article *kb.Article) *KnowledgeBaseSuggestion {
|
||||
return &KnowledgeBaseSuggestion{Url: article.URL, Title: article.Title}
|
||||
},
|
||||
)
|
||||
|
|
|
@ -6,7 +6,10 @@
|
|||
"keywords": [
|
||||
"start",
|
||||
"automatically",
|
||||
"login"
|
||||
"login",
|
||||
"startup",
|
||||
"start-up",
|
||||
"boot"
|
||||
]
|
||||
},
|
||||
{
|
||||
|
@ -14,7 +17,11 @@
|
|||
"url": "https://proton.me/support/bridge-automatic-update",
|
||||
"title": "Automatic Update and Bridge",
|
||||
"keywords": [
|
||||
"TBD"
|
||||
"update",
|
||||
"upgrade",
|
||||
"restart",
|
||||
"automatic",
|
||||
"manual"
|
||||
]
|
||||
},
|
||||
{
|
||||
|
@ -22,7 +29,12 @@
|
|||
"url": "https://proton.me/support/messages-encrypted-via-bridge",
|
||||
"title": "Are my messages encrypted via Proton Mail Bridge?",
|
||||
"keywords": [
|
||||
"TBD"
|
||||
"encrypted",
|
||||
"privacy",
|
||||
"message",
|
||||
"security",
|
||||
"gpg",
|
||||
"pgp"
|
||||
]
|
||||
},
|
||||
{
|
||||
|
@ -70,7 +82,7 @@
|
|||
"url": "https://proton.me/support/update-required",
|
||||
"title": "Update required",
|
||||
"keywords": [
|
||||
"TBD"
|
||||
"update", "upgrade", "restart", "reboot"
|
||||
]
|
||||
},
|
||||
{
|
||||
|
@ -78,7 +90,7 @@
|
|||
"url": "https://proton.me/support/port-already-occupied-error",
|
||||
"title": "Port already occupied error",
|
||||
"keywords": [
|
||||
"TBD"
|
||||
"Port", "occupied", "1143", "1025", "SMTP", "IMAP", "error"
|
||||
]
|
||||
},
|
||||
{
|
||||
|
@ -86,7 +98,7 @@
|
|||
"url": "https://proton.me/support/clients-supported-bridge",
|
||||
"title": "Email clients supported by Proton Mail Bridge",
|
||||
"keywords": [
|
||||
"TBD"
|
||||
"client", "Outlook", "Thunderbird", "Apple Mail", "EM Client", "The Bat", "Eudora", "Postbox"
|
||||
]
|
||||
},
|
||||
{
|
||||
|
@ -94,7 +106,7 @@
|
|||
"url": "https://proton.me/support/imap-smtp-and-pop3-setup",
|
||||
"title": "IMAP, SMTP, and POP3 setup",
|
||||
"keywords": [
|
||||
"TBD"
|
||||
"IMAP", "SMTP", "setup"
|
||||
]
|
||||
},
|
||||
{
|
||||
|
@ -102,7 +114,7 @@
|
|||
"url": "https://proton.me/support/protonmail-bridge-install",
|
||||
"title": "How to install Proton Mail Bridge",
|
||||
"keywords": [
|
||||
"TBD"
|
||||
"install", "setup", "installer"
|
||||
]
|
||||
},
|
||||
{
|
||||
|
@ -110,7 +122,7 @@
|
|||
"url": "https://proton.me/support/bridge-for-linux",
|
||||
"title": "Proton Mail Bridge for Linux",
|
||||
"keywords": [
|
||||
"TBD"
|
||||
"Linux", "Ubuntu", "Fedora", "Debian", "Unix", "deb", "rpm"
|
||||
]
|
||||
},
|
||||
{
|
||||
|
@ -118,7 +130,8 @@
|
|||
"url": "https://proton.me/support/operating-systems-supported-bridge",
|
||||
"title": "System requirements for Proton Mail Bridge",
|
||||
"keywords": [
|
||||
"TBD"
|
||||
"requirement", "cpu", "memory", "Windows 7", "Windows XP", "Windows", "Windows 10", "Windows 11","Catalina", "Sonoma", "Ventura",
|
||||
"Debian", "Ubuntu", "Fedora", "Redhat", "Big Sur", "Monterey"
|
||||
]
|
||||
},
|
||||
{
|
||||
|
@ -126,7 +139,7 @@
|
|||
"url": "https://proton.me/support/protonmail-bridge-configure-client",
|
||||
"title": "How to configure your email client for Proton Mail Bridge",
|
||||
"keywords": [
|
||||
"TBD"
|
||||
"Client", "Outlook", "configure", "setup", "IMAP", "SMTP"
|
||||
]
|
||||
},
|
||||
{
|
||||
|
@ -134,7 +147,7 @@
|
|||
"url": "https://proton.me/support/invalid-password-error-setting-email-client",
|
||||
"title": "Invalid password error while setting up email client",
|
||||
"keywords": [
|
||||
"TBD"
|
||||
"password", "invalid", "error"
|
||||
]
|
||||
},
|
||||
{
|
||||
|
@ -142,7 +155,7 @@
|
|||
"url": "https://proton.me/support/protonmail-bridge-clients-windows-outlook-2019",
|
||||
"title": "Proton Mail Bridge Microsoft Outlook for Windows 2019 setup guide",
|
||||
"keywords": [
|
||||
"TBD"
|
||||
"Outlook", "2019", "setup", "configuration"
|
||||
]
|
||||
},
|
||||
{
|
||||
|
|
|
@ -20,6 +20,11 @@ package kb
|
|||
import (
|
||||
_ "embed"
|
||||
"encoding/json"
|
||||
"regexp"
|
||||
"strings"
|
||||
|
||||
"github.com/bradenaw/juniper/xslices"
|
||||
"golang.org/x/exp/slices"
|
||||
)
|
||||
|
||||
//go:embed kbArticleList.json
|
||||
|
@ -31,9 +36,10 @@ type Article struct {
|
|||
URL string `json:"url"`
|
||||
Title string `json:"title"`
|
||||
Keywords []string `json:"keywords"`
|
||||
Score int
|
||||
}
|
||||
|
||||
type ArticleList []Article
|
||||
type ArticleList []*Article
|
||||
|
||||
// GetArticleList returns the list of KB articles.
|
||||
func GetArticleList() (ArticleList, error) {
|
||||
|
@ -44,17 +50,35 @@ func GetArticleList() (ArticleList, error) {
|
|||
}
|
||||
|
||||
// GetSuggestions return a list of up to 3 suggestions for KB articles matching the given user input.
|
||||
func GetSuggestions(_ string) (ArticleList, error) {
|
||||
func GetSuggestions(userInput string) (ArticleList, error) {
|
||||
userInput = strings.ToUpper(userInput)
|
||||
articles, err := GetArticleList()
|
||||
if err != nil {
|
||||
return ArticleList{}, err
|
||||
}
|
||||
|
||||
// note starting with go 1.21, we will be able to do:
|
||||
// return articles[:min(3, len(articles))]
|
||||
l := len(articles)
|
||||
if l > 3 {
|
||||
l = 3
|
||||
for _, article := range articles {
|
||||
for _, keyword := range article.Keywords {
|
||||
if strings.Contains(userInput, strings.ToUpper(keyword)) {
|
||||
article.Score++
|
||||
}
|
||||
}
|
||||
}
|
||||
return articles[:l], nil
|
||||
|
||||
articles = xslices.Filter(articles, func(article *Article) bool { return article.Score > 0 })
|
||||
slices.SortFunc(articles, func(lhs, rhs *Article) bool { return lhs.Score > rhs.Score })
|
||||
|
||||
if len(articles) > 3 {
|
||||
return articles[:3], nil
|
||||
}
|
||||
|
||||
return articles, nil
|
||||
}
|
||||
|
||||
func simplifyUserInput(input string) string {
|
||||
// replace any sequence not matching of the following with a single space:
|
||||
// - letters in any language (accentuated or not)
|
||||
// - numbers
|
||||
// - the apostrophe character '
|
||||
return strings.TrimSpace(regexp.MustCompile(`[^\p{L}\p{N}']+`).ReplaceAllString(input, " "))
|
||||
}
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
package kb
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
|
@ -39,7 +40,18 @@ func Test_ArticleList(t *testing.T) {
|
|||
}
|
||||
|
||||
func Test_GetSuggestions(t *testing.T) {
|
||||
suggestions, err := GetSuggestions("")
|
||||
suggestions, err := GetSuggestions("Thunderbird is not working, error during password")
|
||||
require.NoError(t, err)
|
||||
require.True(t, len(suggestions) <= 3)
|
||||
for _, article := range suggestions {
|
||||
fmt.Printf("Score: %v - %#v\n", article.Score, article.Title)
|
||||
}
|
||||
|
||||
suggestions, err = GetSuggestions("Supercalifragilisticexpialidocious Sesquipedalian Worcestershire")
|
||||
require.NoError(t, err)
|
||||
require.Empty(t, suggestions)
|
||||
}
|
||||
|
||||
func Test_simplifyUserInput(t *testing.T) {
|
||||
require.Equal(t, "word1 ñóÄ don't déjà 33 pizza", simplifyUserInput(" \nword1 \n\tñóÄ don't\n\n\ndéjà, 33 pizza=🍕\n,\n"))
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue