Class: Teri::OpenAIClient
- Inherits:
-
Object
- Object
- Teri::OpenAIClient
- Defined in:
- lib/teri/openai_client.rb
Instance Attribute Summary collapse
-
#client ⇒ Object
readonly
Returns the value of attribute client.
-
#logger ⇒ Object
readonly
Returns the value of attribute logger.
-
#model ⇒ Object
readonly
Returns the value of attribute model.
Instance Method Summary collapse
-
#build_prompt(transaction, accounting) ⇒ String
Build a prompt for the OpenAI API.
-
#initialize(options = {}) ⇒ OpenAIClient
constructor
A new instance of OpenAIClient.
-
#suggest_category(transaction, accounting) ⇒ Hash
Get a suggested category for a transaction based on its details and previous codings.
Constructor Details
#initialize(options = {}) ⇒ OpenAIClient
Returns a new instance of OpenAIClient.
9 10 11 12 13 14 15 16 17 18 19 20 |
# File 'lib/teri/openai_client.rb', line 9 def initialize( = {}) @api_key = [:api_key] || ENV.fetch('OPENAI_API_KEY', nil) unless @api_key raise 'OpenAI API key not found. Please set OPENAI_API_KEY environment variable or provide it as an argument.' end @model = [:model] || 'gpt-3.5-turbo' @client = OpenAI::Client.new(access_token: @api_key) # Set up logging setup_logger([:log_file]) end |
Instance Attribute Details
#client ⇒ Object (readonly)
Returns the value of attribute client.
7 8 9 |
# File 'lib/teri/openai_client.rb', line 7 def client @client end |
#logger ⇒ Object (readonly)
Returns the value of attribute logger.
7 8 9 |
# File 'lib/teri/openai_client.rb', line 7 def logger @logger end |
#model ⇒ Object (readonly)
Returns the value of attribute model.
7 8 9 |
# File 'lib/teri/openai_client.rb', line 7 def model @model end |
Instance Method Details
#build_prompt(transaction, accounting) ⇒ String
Build a prompt for the OpenAI API
64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 |
# File 'lib/teri/openai_client.rb', line 64 def build_prompt(transaction, accounting) prompt = "Transaction details:\n" prompt += "Date: #{transaction.date}\n" prompt += "Description: #{transaction.description}\n" prompt += "Memo: #{transaction.memo}\n" if transaction.respond_to?(:memo) && transaction.memo prompt += "Amount: #{transaction.amount}\n" if transaction.respond_to?(:amount) if transaction.respond_to?(:counterparty) && transaction.counterparty prompt += "Counterparty: #{transaction.counterparty}\n" end if transaction.respond_to?(:hints) && transaction.hints && !transaction.hints.empty? prompt += "\nHints from previous categorizations:\n" transaction.hints.each do |hint| prompt += "- #{hint}\n" end end # Add previous codings section if available if accounting.respond_to?(:previous_codings) && accounting.previous_codings && !accounting.previous_codings.empty? prompt += "\nPrevious codings:\n" accounting.previous_codings.each do |desc, info| next unless info.is_a?(Hash) prompt += if info[:hints] && !info[:hints].empty? "- \"#{desc}\" => #{info[:category]} (hints: #{info[:hints].join(', ')})\n" else "- \"#{desc}\" => #{info[:category]}\n" end end end # Add counterparty hints if available if accounting.respond_to?(:counterparty_hints) && transaction.respond_to?(:counterparty) && transaction.counterparty && accounting.counterparty_hints[transaction.counterparty] prompt += "\nCounterparty information:\n" accounting.counterparty_hints[transaction.counterparty].each do |hint| prompt += "- #{hint}\n" end end prompt += "\nPlease respond with a JSON object containing:\n" prompt += "- category: The suggested category (e.g., 'Expenses:Office')\n" prompt += "- confidence: A number between 0-100 indicating your confidence\n" prompt += "- explanation: A brief explanation of your suggestion\n" prompt end |
#suggest_category(transaction, accounting) ⇒ Hash
Get a suggested category for a transaction based on its details and previous codings
26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 |
# File 'lib/teri/openai_client.rb', line 26 def suggest_category(transaction, accounting) previous_codings = accounting.respond_to?(:previous_codings) ? accounting.previous_codings : {} counterparty_hints = accounting.respond_to?(:counterparty_hints) ? accounting.counterparty_hints : {} available_categories = [] # Prepare the prompt with transaction details prompt = build_prompt(transaction, accounting) # Log the previous_codings for debugging if @logger @logger.info("PREVIOUS_CODINGS: #{previous_codings.inspect}") @logger.info("COUNTERPARTY_HINTS: #{counterparty_hints.inspect}") end # Log the prompt @logger&.info("PROMPT: #{prompt}") # Call the OpenAI API response = @client.chat( parameters: { model: @model, messages: [ { role: 'user', content: prompt }, ], } ) # Log the response @logger&.info("RESPONSE: #{response.dig('choices', 0, 'message', 'content')}") # Parse the response parse_suggestion(response, available_categories) end |