@postalsys/email-text-tools 1.2.3 → 1.2.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,7 +1,7 @@
1
1
  'use strict';
2
2
 
3
3
  const fs = require('fs').promises;
4
- const extractReply = require('../lib/extract-reply');
4
+ const generateSummary = require('../lib/generate-summary');
5
5
  const simpleParser = require('mailparser').simpleParser;
6
6
 
7
7
  async function main() {
@@ -9,7 +9,7 @@ async function main() {
9
9
 
10
10
  const parsed = await simpleParser(eml);
11
11
 
12
- const replyText = await extractReply(
12
+ const summary = await generateSummary(
13
13
  {
14
14
  html: parsed.html,
15
15
  text: parsed.text
@@ -17,7 +17,7 @@ async function main() {
17
17
  process.env.OPENAI_API_KEY
18
18
  );
19
19
 
20
- console.log(replyText);
20
+ console.log(summary);
21
21
  }
22
22
 
23
23
  main();
package/index.js CHANGED
@@ -5,6 +5,6 @@ const htmlToText = require('./lib/html-to-text');
5
5
  const inlineHtml = require('./lib/inline-html');
6
6
  const inlineText = require('./lib/inline-text');
7
7
  const mimeHtml = require('./lib/mime-html');
8
- const extractReply = require('./lib/extract-reply');
8
+ const generateSummary = require('./lib/generate-summary');
9
9
 
10
- module.exports = { textToHtml, htmlToText, inlineHtml, inlineText, mimeHtml, extractReply };
10
+ module.exports = { textToHtml, htmlToText, inlineHtml, inlineText, mimeHtml, generateSummary };
@@ -8,9 +8,23 @@ const fetchCmd = global.fetch || nodeFetch;
8
8
  const MAX_TEXT_LENGTH = 6 * 1024;
9
9
  const OPENAI_API_URL = 'https://api.openai.com/v1/chat/completions';
10
10
 
11
- const PROMPT = `If the following email message includes a reply text, return it. If the message ends with a courtesy greeting, do not include it in the response. Extract the main content text if the message does not contain a reply. Do not add a comment, only return the message text or an empty response if you can not detect any text content. Here is the email message content:`;
12
-
13
- async function extractReply(message, apiToken) {
11
+ const SYSTEM_PROMPT = `
12
+ I want you to act as an email client that processes emails and highlights important parts.
13
+ You do not comment or explain anything.
14
+ `
15
+ .replace(/\s+/g, ' ')
16
+ .trim();
17
+
18
+ const USER_PROMPT = `
19
+ Describe the sentiment of the email using one word. Use either "positive", "neutral" or "negative". Prefix the sentiment with "Sentiment:".
20
+ On a separate line, write a one-sentence summary of the email. Prefix the summary with "Summary:".
21
+ I want you to only reply with the sentiment and summary, do not write explanations.
22
+ All the text that follows from now on is the email message:
23
+ `
24
+ .replace(/\s+/g, ' ')
25
+ .trim();
26
+
27
+ async function generateSummary(message, apiToken) {
14
28
  let text = message.text;
15
29
  if (!text && message.html) {
16
30
  text = htmlToText(message.text);
@@ -30,9 +44,13 @@ async function extractReply(message, apiToken) {
30
44
  let payload = {
31
45
  model: 'gpt-3.5-turbo',
32
46
  messages: [
47
+ {
48
+ role: 'system',
49
+ content: `${SYSTEM_PROMPT}`
50
+ },
33
51
  {
34
52
  role: 'user',
35
- content: `${PROMPT}
53
+ content: `${USER_PROMPT}
36
54
 
37
55
  ${text}`
38
56
  }
@@ -67,8 +85,6 @@ ${text}`
67
85
  throw new Error(`Failed to POST API request`);
68
86
  }
69
87
 
70
- console.log('OPENAI RESPONSE', JSON.stringify(data, false, 2));
71
-
72
88
  let output =
73
89
  data &&
74
90
  data.choices &&
@@ -81,13 +97,27 @@ ${text}`
81
97
  .replace(/^\s*"|"\s*$/g, '')
82
98
  .trim();
83
99
 
84
- const response = {
85
- id: data && data.id,
86
- tokens: data && data.usage && data.usage.total_tokens,
87
- text: output
88
- };
100
+ let structured = {};
101
+
102
+ let summaryMatch = output.match(/\bsummary:\s*(.*)$/im);
103
+ if (summaryMatch) {
104
+ structured.summary = summaryMatch[1].replace(/^["'\s]+|["'\s]+$/g, '');
105
+ }
106
+
107
+ let sentimentMatch = output.match(/\bsentiment:\s*(.*)$/im);
108
+ if (sentimentMatch) {
109
+ structured.sentiment = sentimentMatch[1].replace(/^["'\s]+|["'\s]+$/g, '').toLowerCase();
110
+ }
111
+
112
+ const response = Object.assign(
113
+ {
114
+ id: data && data.id,
115
+ tokens: data && data.usage && data.usage.total_tokens
116
+ },
117
+ structured
118
+ );
89
119
 
90
120
  return response;
91
121
  }
92
122
 
93
- module.exports = extractReply;
123
+ module.exports = generateSummary;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@postalsys/email-text-tools",
3
- "version": "1.2.3",
3
+ "version": "1.2.4",
4
4
  "description": "Email text tools",
5
5
  "main": "index.js",
6
6
  "scripts": {
@@ -34,6 +34,6 @@
34
34
  "moment-timezone": "0.5.41",
35
35
  "node-fetch": "2.6.7",
36
36
  "node-html-parser": "6.1.5",
37
- "tlds": "1.236.0"
37
+ "tlds": "1.237.0"
38
38
  }
39
39
  }