summarize-meeting 1.0.0 → 1.2.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 502d04b52ca4fb6aeba632d7d9959ef043db57cd7f70f9de278a5fc70f52a034
4
- data.tar.gz: b1aae558f143f92a5d21e0f5268025768ef517b1ace5773c5f4b44a0b9fab10d
3
+ metadata.gz: 50b154d8f5d117b51fb3a377ad725088262543c05d5ee2614929511ad093a553
4
+ data.tar.gz: 66f0a4144e8b5bf6d36792bdb0432014b803e4eff020060fc9d5045c1631edef
5
5
  SHA512:
6
- metadata.gz: 781f9a4108fce791c7355e73161922b1271d8c7aefadc878dedadc5dfeec5b7a408a454c0d93d20912dd897a16b8c017ea6a4fcda27d2859fd90e252538163ae
7
- data.tar.gz: 7b01038c1cd4a0473d98338131866fb751b471fcdffa49e91619ce12d0e83cf8dddf68814dbaf2c822e29d3d43c9260a0dbcb44d304f6bd4f4aee9e262ca8210
6
+ metadata.gz: fd077cdfe8a177d145a5ab4672d14477cbd7a06124f0eeb03c834ef5eb632022d76920ab1ee6cba38e81204f91faa48cb1bdcc1683a86db1f7305e232cc3380a
7
+ data.tar.gz: fc2061143753fc8865b39702cfc215ae7732f8e697f8288170f07a8ba1f627c3078f4d37c40e725506413a2718cb5b7b3f93d427cd6d94a3d1ee7f0d30246192
@@ -1,11 +1,17 @@
1
- require "openai"
2
-
3
1
  module SummarizeMeeting
4
2
  module Ai
3
+ class OpenAiError < StandardError; end
4
+ MAX_TOTAL_TOKENS = 4096
5
+ WORDS_PER_TOKEN = 0.75
6
+
5
7
  @@access_token = ENV["OPENAI_KEY"]
6
8
  @@organization_id = ENV["OPENAI_ORG"]
7
9
 
8
10
  def self.client
11
+ @client ||= new_client(access_token: access_token, organization_id: organization_id)
12
+ end
13
+
14
+ def self.new_client(access_token:, organization_id:)
9
15
  OpenAI::Client.new(access_token: access_token, organization_id: organization_id)
10
16
  end
11
17
 
@@ -24,5 +30,27 @@ module SummarizeMeeting
24
30
  def self.organization_id=(id)
25
31
  @@organization_id = id
26
32
  end
33
+
34
+ def self.calculate_token_word_count(token_count)
35
+ (token_count * WORDS_PER_TOKEN.to_f).ceil
36
+ end
37
+
38
+ def self.calculate_word_token_count(word_count)
39
+ (word_count / WORDS_PER_TOKEN.to_f).ceil
40
+ end
41
+
42
+ def self.chat(messages, client: self.client)
43
+ parameters = {
44
+ model: "gpt-3.5-turbo",
45
+ messages: messages,
46
+ }
47
+ response = client.chat(parameters: parameters)
48
+ content = response.dig("choices", 0, "message", "content")
49
+ if !content
50
+ raise OpenAiError, "No response from OpenAI"
51
+ else
52
+ content
53
+ end
54
+ end
27
55
  end
28
56
  end
@@ -4,6 +4,8 @@ require "openai"
4
4
 
5
5
  module SummarizeMeeting
6
6
  class Meeting
7
+ RESPONSE_RESERVE_TOKENS = 500
8
+
7
9
  LINE_SUMMARY_PROMPT_TEMPLATE = [
8
10
  {
9
11
  role: "system",
@@ -11,7 +13,7 @@ module SummarizeMeeting
11
13
  },
12
14
  {
13
15
  role: "system",
14
- content: "The transcript of the meeting is split into {{chunkCount}} chunks. This is the {{chunkIndex}} chunk.",
16
+ content: "The transcript of the meeting is split into {{chunkCount}} chunks. This is the chunk number {{chunkIndex}} of {{chunkCount}}.",
15
17
  },
16
18
  {
17
19
  role: "assistant",
@@ -60,17 +62,14 @@ module SummarizeMeeting
60
62
  attr_reader :transcript
61
63
 
62
64
  def summarize
63
-
64
65
  # Step 1. Split the transcript into lines.
65
66
  lines = transcript.lines
66
67
 
67
68
  # Step 2. Calculate the maximum chunk size in words.
68
- max_total_tokens = 4000
69
- response_token_reserve = 500
70
- template_tokens = LINE_SUMMARY_PROMPT_TEMPLATE.map { |line| line[:content].split.size }.sum
71
- max_chunk_tokens = max_total_tokens - response_token_reserve - template_tokens
72
- words_per_token = 0.7
73
- max_chunk_word_count = max_chunk_tokens * words_per_token
69
+ template_word_count = LINE_SUMMARY_PROMPT_TEMPLATE.map { |line| line[:content].split.size }.sum
70
+ template_token_count = SummarizeMeeting::Ai.calculate_word_token_count(template_word_count)
71
+ max_chunk_token_count = SummarizeMeeting::Ai::MAX_TOTAL_TOKENS - RESPONSE_RESERVE_TOKENS - template_token_count
72
+ max_chunk_word_count = SummarizeMeeting::Ai.calculate_token_word_count(max_chunk_token_count)
74
73
 
75
74
  # Step 3. Split the transcript into equally sized chunks.
76
75
  chunks = split_lines_into_equal_size_chunks(lines, max_chunk_word_count)
@@ -86,27 +85,14 @@ module SummarizeMeeting
86
85
  consolidated_template = CONSOLIDATED_SUMMARY_PROMPT_TEMPLATE
87
86
  prompt = Mustache.render(consolidated_template.to_json, { notes: previous_chunks_summary.to_json })
88
87
  messages = JSON.parse(prompt)
89
- response = SummarizeMeeting::Ai.client.chat(
90
- parameters: {
91
- model: "gpt-3.5-turbo",
92
- messages: messages,
93
- }
94
- )
95
- response.dig("choices", 0, "message", "content")
88
+ SummarizeMeeting::Ai.chat(messages)
96
89
  end
97
90
 
98
91
  def summarize_chunk(chunk, chunk_index, chunk_count, previous_chunks_summary)
99
92
  template = LINE_SUMMARY_PROMPT_TEMPLATE
100
93
  prompt = Mustache.render(template.to_json, { chunkCount: chunk_count, chunkIndex: chunk_index + 1, chunk: chunk.join("\n").to_json })
101
94
  messages = JSON.parse(prompt)
102
-
103
- response = SummarizeMeeting::Ai.client.chat(
104
- parameters: {
105
- model: "gpt-3.5-turbo",
106
- messages: messages,
107
- }
108
- )
109
- response.dig("choices", 0, "message", "content")
95
+ SummarizeMeeting::Ai.chat(messages)
110
96
  end
111
97
 
112
98
  def split_lines_into_equal_size_chunks(lines, max_chunk_word_count)
@@ -1,3 +1,3 @@
1
1
  module SummarizeMeeting
2
- VERSION = "1.0.0"
2
+ VERSION = "1.2.0"
3
3
  end
@@ -3,4 +3,4 @@ require_relative "./summarize-meeting/ai"
3
3
  require_relative "./summarize-meeting/meeting"
4
4
 
5
5
  module SummarizeMeeting
6
- end
6
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: summarize-meeting
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.0
4
+ version: 1.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Sean Devine
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2023-03-03 00:00:00.000000000 Z
11
+ date: 2023-03-04 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: optparse