patterns-ai-core / ecommerce-ai-assistant-demo

An e-commerce AI assistant built with Langchain.rb
MIT License
43 stars 6 forks source link

Update to order item doesnt update the object `OrderItem` #5

Open palladius opened 2 months ago

palladius commented 2 months ago

Model: Gemini 1.5 Flash

Update to order item doesnt update the object OrderItem. Look at this trace:

In line 21, we create an order with order_items = [{"quantity"=>5, "product_sku"=>"Y3048509"}]:

21|🤖 [model] 🛠️ [1/1] 🛠️  {"name"=>"order_management__create_order", "args"=>{"customer_id"=>3, "order_items"=>[{"quantity"=>5, "product_sku"=>"Y3048509"}]}}
22|🔢 [func] 🛠️  order_management__create_order => {:success=>true, :order_id=>1}
23|🤖 [model] 🛠️ [1/1] 🛠️  {"name"=>"shipping_service__create_shipping_label", "args"=>{"customer_id"=>3, "address"=>"667 Madison Avenue, New York, NY 10065", "provider"=>"fedex"}}
24|🔢 [func] 🛠️  shipping_service__create_shipping_label => {:success=>true, :tracking_number=>"f021b91e-3676-4037-a5c5-a5b6b5f96b4a", :provider=>"fedex"}
25|🤖 [model] 🛠️ [1/1] 🛠️  {"name"=>"email_service__send_email", "args"=>{"order_id"=>1, "customer_id"=>3}}

== DB DUMP ==
1. Products:
{:sku=>"A3045809", :price=>20.99, :quantity=>100}
{:sku=>"B9384509", :price=>21.99, :quantity=>5}
{:sku=>"Z0394853", :price=>22.99, :quantity=>20}
{:sku=>"X3048509", :price=>23.99, :quantity=>3}
{:sku=>"Y3048509", :price=>24.99, :quantity=>5}
{:sku=>"L3048509", :price=>29.99, :quantity=>0}
X. orders:
{:id=>1, :customer_id=>3, :created_at=>2024-09-09 08:46:57.899212 +0200}
X. order_items:
{:id=>1, :order_id=>1, :product_sku=>nil, :quantity=>nil}
X. products:
[...]

However, the order_items[1] contains only NIL for product_sku and quantity.

Is it Gemini or a bug in the code?

palladius commented 2 months ago

Problem might be in the constructor. Here's my log:

E, [2024-09-09T09:02:48.503990 #40892] ERROR -- : [Langchain.rb] Error running tools: undefined method `sku' for nil; /Users/ricc/git/ecommerce-ai-assistant-demo-gemini/tools/email_service.rb:36:in `block (2 levels) in send_email'\n/Users/ricc/git/ecommerce-ai-assistant-demo-gemini/tools/email_service.rb:36:in `map'\n/Users/ricc/git/ecommerce-ai-assistant-demo-gemini/tools/email_service.rb:36:in `block in send_email'\n/Users/ricc/.rbenv/versions/3.3.4/lib/ruby/gems/3.3.0/gems/mail-2.8.1/lib/mail/message.rb:151:in `instance_eval'\n/Users/ricc/.rbenv/versions/3.3.4/lib/ruby/gems/3.3.0/gems/mail-2.8.1/lib/mail/message.rb:151:in `initialize'\n/Users/ricc/.rbenv/versions/3.3.4/lib/ruby/gems/3.3.0/gems/mail-2.8.1/lib/mail/mail.rb:51:in `new'\n/Users/ricc/.rbenv/versions/3.3.4/lib/ruby/gems/3.3.0/gems/mail-2.8.1/lib/mail/mail.rb:51:in `new'\n/Users/ricc/.rbenv/versions/3.3.4/lib/ruby/gems/3.3.0/gems/mail-2.8.1/lib/mail/mail.rb:132:in `deliver'\n/Users/ricc/git/ecommerce-ai-assistant-demo-gemini/tools/email_service.rb:26:in `send_email'\n/Users/ricc/.rbenv/versions/3.3.4/lib/ruby/gems/3.3.0/bundler/gems/langchainrb-860deef98cd6/lib/langchain/assistants/assistant.rb:321:in `block in run_tools'\n/Users/ricc/.rbenv/versions/3.3.4/lib/ruby/gems/3.3.0/bundler/gems/langchainrb-860deef98cd6/lib/langchain/assistants/assistant.rb:314:in `each'\n/Users/ricc/.rbenv/versions/3.3.4/lib/ruby/gems/3.3.0/bundler/gems/langchainrb-860deef98cd6/lib/langchain/assistants/assistant.rb:314:in `run_tools'\n/Users/ricc/.rbenv/versions/3.3.4/lib/ruby/gems/3.3.0/bundler/gems/langchainrb-860deef98cd6/lib/langchain/assistants/assistant.rb:263:in `execute_tools'\n/Users/ricc/.rbenv/versions/3.3.4/lib/ruby/gems/3.3.0/bundler/gems/langchainrb-860deef98cd6/lib/langchain/assistants/assistant.rb:189:in `handle_state'\n/Users/ricc/.rbenv/versions/3.3.4/lib/ruby/gems/3.3.0/bundler/gems/langchainrb-860deef98cd6/lib/langchain/assistants/assistant.rb:105:in `run'\n/Users/ricc/.rbenv/versions/3.3.4/lib/ruby/gems/3.3.0/bundler/gems/langchainrb-860deef98cd6/lib/langchain/assistants/assistant.rb:117:in `add_message_and_run'\n/Users/ricc/git/ecommerce-ai-assistant-demo-gemini/lib/assistant.rb:7:in `msg'\n(irb):1:in `<top (required)>'\n/Users/ricc/.rbenv/versions/3.3.4/lib/ruby/3.3.0/irb/workspace.rb:121:in `eval'\n/Users/ricc/.rbenv/versions/3.3.4/lib/ruby/3.3.0/irb/workspace.rb:121:in `evaluate'\n/Users/ricc/.rbenv/versions/3.3.4/lib/ruby/3.3.0/irb/context.rb:633:in `evaluate_expression'\n/Users/ricc/.rbenv/versions/3.3.4/lib/ruby/3.3.0/irb/context.rb:600:in `evaluate'\n/Users/ricc/.rbenv/versions/3.3.4/lib/ruby/3.3.0/irb.rb:1049:in `block (2 levels) in eval_input'\n/Users/ricc/.rbenv/versions/3.3.4/lib/ruby/3.3.0/irb.rb:1380:in `signal_status'\n/Users/ricc/.rbenv/versions/3.3.4/lib/ruby/3.3.0/irb.rb:1041:in `block in eval_input'\n/Users/ricc/.rbenv/versions/3.3.4/lib/ruby/3.3.0/irb.rb:1120:in `block in each_top_level_statement'\n<internal:kernel>:187:in `loop'\n/Users/ricc/.rbenv/versions/3.3.4/lib/ruby/3.3.0/irb.rb:1117:in `each_top_level_statement'\n/Users/ricc/.rbenv/versions/3.3.4/lib/ruby/3.3.0/irb.rb:1040:in `eval_input'\n/Users/ricc/.rbenv/versions/3.3.4/lib/ruby/3.3.0/irb.rb:1021:in `block in run'\n/Users/ricc/.rbenv/versions/3.3.4/lib/ruby/3.3.0/irb.rb:1020:in `catch'\n/Users/ricc/.rbenv/versions/3.3.4/lib/ruby/3.3.0/irb.rb:1020:in `run'\n/Users/ricc/.rbenv/versions/3.3.4/lib/ruby/3.3.0/irb.rb:904:in `start'\ntest-e2e.rb:105:in `<main>'

Maybe we need to alias sku to product_sku or something?

palladius commented 2 months ago

Maybe I found the bug, look:

irb(main):014> OrderManagement.new.create_order(order_items: [{"quantity"=>7, "product_sku"=>"Z0394853"}], "customer_id": 3)
I, [2024-09-09T09:09:51.612745 #45499]  INFO -- : [Langchain.rb] [OrderManagement]: [ 📦 ] Creating Order record for customer ID: 3
=> {:success=>true, :order_id=>3}
irb(main):015> OrderManagement.new.create_order(order_items: [{quantity: 7, product_sku: "Z0394853"}], "customer_id": 3)
I, [2024-09-09T09:10:11.903878 #45499]  INFO -- : [Langchain.rb] [OrderManagement]: [ 📦 ] Creating Order record for customer ID: 3
=> {:success=>true, :order_id=>4}

So if the arg is a symbol it works, if its a string it doesn't. I believe the solution is to change the

      ret = OrderItem.create(order_id: order.id, product_sku: item[:product_sku], quantity: item[:quantity])

to get either item[:product_sku] or item['product_sku'] and so on

palladius commented 2 months ago

... and found the fix!


class OrderManagement
  extend Langchain::ToolDefinition

[...]

def create_order

[..]
    order_items.each do |item|
      # original
      OrderItem.create(order_id: order.id, product_sku: item[:product_sku], quantity: item[:quantity])
       # ricc fix 
      either_product_sku = item.fetch(:product_sku, item.fetch('product_sku'))
      either_quantity = item.fetch(:quantity, item.fetch('quantity'))
      OrderItem.create(order_id: order.id, product_sku: either_product_sku, quantity: either_quantity)
    end
[...]
end
palladius commented 2 months ago

I fixed it in my fork: https://github.com/palladius/ecommerce-ai-assistant-demo-gemini/commit/7bfa9f6895d3c76f311f22259c6d299c300e3471#diff-f8652a3e74882437289774f0d344d1436a66a2c3c7ca528e83b73798cf7929f7