<commit_before>const simpleNLP = require('simple-nlp');

simpleNLP.init()
    .then(() => {
        console.log('Language processing ready');
    });

const tokenize = phrase => {
    return simpleNLP.analyzePhrase(phrase);
};

const getWordMatches = (analysis, targets) => {
    const matches = targets.map(target => {
        const words = target.keywords;
        const matchingWords = words.map(target => {
            const word = target.word;
            const type = target.type;
            return _.some(analysis.wordsByType[type], foundWord => foundWord === word);
        }).filter((a) => a);
        return {
            target: target.title,
            match: (matchingWords.length / words.length).toFixed(2)
        };
    });
    return matches;
};

const selectClient = (tokenizedMessage, actionConfigs) => {
    console.log('Selecting the best action for phrase', tokenizedMessage.originalMessage);
    console.log('Client choices');
    console.dir(actionConfigs);
    const matchingClients = actionConfigs.map(client => {
        const matchingActions = Object.keys(client.actions).map(actionKey => {
            const action = client.actions[actionKey];
            const keywordMatches = action.keywords.map(keyword => {
                const keywordType = keyword.type.toUpperCase();
                if (tokenizedMessage.wordsByType[keywordType] &&
                    tokenizedMessage.wordsByType[keywordType].indexOf(keyword.word) !== -1) {
                    return keyword;
                }
            }).filter(w => w !== undefined);
            console.dir(keywordMatches);
            const hitRate = keywordMatches.length; // keywordMatches.length / action.keywords.length;
            console.log(`Hit rate for ${actionKey}: ${hitRate}`);
            if (hitRate > 0) {
                return {
                    action: actionKey,
                    matchingKeywords: keywordMatches,<commit_msg>Support for exact phrase in action config<commit_after>const simpleNLP = require('simple-nlp');

simpleNLP.init()
    .then(() => {
        console.log('Language processing ready');
    });

const tokenize = phrase => {
    return simpleNLP.analyzePhrase(phrase);
};

const getWordMatches = (analysis, targets) => {
    const matches = targets.map(target => {
        const words = target.keywords;
        const matchingWords = words.map(target => {
            const word = target.word;
            const type = target.type;
            return _.some(analysis.wordsByType[type], foundWord => foundWord === word);
        }).filter((a) => a);
        return {
            target: target.title,
            match: (matchingWords.length / words.length).toFixed(2)
        };
    });
    return matches;
};

const selectClient = (tokenizedMessage, actionConfigs) => {
    console.log('Selecting the best action for phrase', tokenizedMessage.originalMessage);
    console.log('Client choices');
    console.dir(actionConfigs);
    const matchingClients = actionConfigs.map(client => {
        const matchingActions = Object.keys(client.actions).map(actionKey => {
            const action = client.actions[actionKey];
            const exactPhrase = action.exactPhrase || '';
            if (exactPhrase.toLowerCase() === tokenizedMessage.originalMessage.toLowerCase()) {
                return {
                    client: client,
                    action: actionKey
                };
            }
            const keywordMatches = action.keywords.map(keyword => {
                const keywordType = keyword.type.toUpperCase();
                if (tokenizedMessage.wordsByType[keywordType] &&
                    tokenizedMessage.wordsByType[keywordType].indexOf(keyword.word) !== -1) {
                    return keyword;
                }
            }).filter(w => w !== undefined);
            console.dir(keywordMatches);
            const hitRate = keywordMatches.length; // keywordMatches.length / action.keywords.length;
            console.log(`Hit rate for ${actionKey}: ${hitRate}`);
            if (hitRate > 0) {
                return {
                    action: actionKey,
                    matchingKeywords: keywordMatches,
{'fraction_non_alphanumeric': 0.12027737924438067, 'fraction_numerical': 0.0014347202295552368, 'mean_word_length': 2.168939393939394, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 29, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '7427009', 'n_tokens_mistral': 1093, 'n_tokens_neox': 1057, 'n_words': 224}