patterns-ai-core / langchainrb

Build LLM-powered applications in Ruby
https://rubydoc.info/gems/langchainrb
MIT License
1.39k stars 194 forks source link

Add colorful message to_s() to threads to make it humanly pleasing and appealing #756

Open palladius opened 1 month ago

palladius commented 1 month ago

Maybe this can help your demo Andrei. I've done this for my demo in Verona and 4mo after its still good code :)

require 'colorize'

module Langchain
  module Messages
    class GoogleGeminiMessage
      def to_s
        # ๐Ÿ’ฌ
        # fun call
        if tool_calls.any?
          # for every tool_calls print one line:
          # ๐Ÿค– [model] ๐Ÿ› ๏ธ [1/2] ๐Ÿ› ๏ธ  {"name"=>"news_retriever__get_top_headlines", ..
          # ๐Ÿค– [model] ๐Ÿ› ๏ธ [2/2] ๐Ÿ› ๏ธ  {"name"=>"....",
          #return # test, should just be "\n"
          tool_calls.enum_for(:each_with_index).map do |tool_call, ix|
            return "๐Ÿค– [#{role}] ๐Ÿ› ๏ธ [#{ix + 1}/#{tool_calls.count}] ๐Ÿ› ๏ธ  #{begin
              tool_call['functionCall'].to_s.force_encoding('UTF-8').colorize(:gray)
            rescue StandardError
              $ERROR_INFO
            end}"
          end.join("\n")
          # return "๐Ÿค– [#{role}] ๐Ÿ› ๏ธ #{self.tool_calls[0]['functionCall'].to_s.force_encoding("UTF-8").colorize(:gray) rescue $!}" if self.tool_calls.any?
        end

        redaction_length = 3000
        sanitized_content = content.force_encoding('UTF-8').strip rescue content 
        if sanitized_content.length > redaction_length
          sanitized_content = "#{sanitized_content.first(redaction_length)}.. (๐Ÿคฅ redacted)"
        end

        # model
        return "๐Ÿค– [modl] ๐Ÿ’ฌ #{sanitized_content.colorize :cyan}" if role == 'model'
        # user
        return "๐Ÿง‘ [user] ๐Ÿ’ฌ #{sanitized_content.colorize :yellow}" if role == 'user'
        # function ๐Ÿ–ฉ would be great but too small ๐Ÿงฎ this is nice
        if role == 'function'
          return "๐Ÿ”ข [func] ๐Ÿ› ๏ธ  #{tool_call_id.force_encoding('UTF-8').colorize :white} => #{sanitized_content.colorize :gray}"
        end
        puts("Something weird happened here! role=#{role} #{self.inspect}")
        # if everything else fails...
        inspect # :status, :code, :message, ...
      end
    end
  end
end

Demo:

messages = assistant.add_message_and_run content: "Whats the weather like in San francisco, CA?",  auto_tool_execution: true
messages.each do |m|
  puts(" - #{m}")
end

==>

 - ๐Ÿง‘ [user] ๐Ÿ’ฌ Whats the weather like in San francisco, CA?
 - ๐Ÿค– [model] ๐Ÿ› ๏ธ [1/1] ๐Ÿ› ๏ธ  {"name"=>"langchain_tool_weather__get_current_weather", "args"=>{"state_code"=>"CA", "city"=>"San Francisco"}}
 - ๐Ÿ”ข [func] ๐Ÿ› ๏ธ  langchain_tool_weather__get_current_weather => Location not found
 - ๐Ÿค– [modl] ๐Ÿ’ฌ I'm sorry, I don't have any information about the weather in San Francisco, CA.
palladius commented 1 month ago

(of course this can be generalized to OpenAI et al, I just battle tested it for Gemini and I know it works for it.)

palladius commented 1 month ago

Better demo:

$ ruby 06-llm-news-test.rb 
I, [2024-09-03T14:56:42.792026 #3162375]  INFO -- : [Langchain.rb] [Langchain::Assistant]: Sending a call to Langchain::LLM::GoogleGemini
I, [2024-09-03T14:56:44.696304 #3162375]  INFO -- : [Langchain.rb] [Langchain::Tool::NewsRetriever]: Retrieving top news headlines
I, [2024-09-03T14:56:45.153318 #3162375]  INFO -- : [Langchain.rb] [Langchain::Assistant]: Sending a call to Langchain::LLM::GoogleGemini
 - ๐Ÿง‘ [user] ๐Ÿ’ฌ  Whats going on in Italy?
 - ๐Ÿค– [mode] โ–ถ๏ธ๐Ÿ› ๏ธ [1/1] Request: {"name"=>"langchain_tool_news_retriever__get_top_headlines", "args"=>{"country"=>"it"}}
 - ๐Ÿ”ข [func] โ—€๏ธ๐Ÿ› ๏ธ  langchain_tool_news_retriever__get_top_headlines => {"status":"ok","totalResults":34,"articles":[{"source":{"id":"google-news","name":"Google News"},"author":"Corriere della Sera","title":"Teo Teocoli su Adriano Celentano: ยซEravamo amicissimi, da cinque anni non mi risponde piรน al telefonoยป - Corriere della Sera","description":null,"url":"https://news.google.com/rss/articles/CBMinAJBVV95cUxON3k5TjYxR3VTQVN6Rk0yNEFJN2dKLVZXUlE2N0F2U0xUVEtUa2RVaDdEUGYxR2J1VUh2NzBBZ0pYaDROZU5TcmNlaDlZVEIxUHVjVjdXeUg5Mk9qXy1RVE5tRnNIbnlhMVVkSGF6NERKbGNIWkNJak84cUhyQ1ZIRThOUFJXMFJtUTFOSnpZMlJTTHg1czV0bDl0WS1HbFNBVHdoWkQyLWt4clhFLVVldHFfNTZVTjFSRW50R3czaElKQUNlWF9FRjlhVXV6YjhNWWlsX2wya0tjUEo0TTRLVExCRC05QjNLQllZNEFFdUJVMUs0UzNRRVNtb0hoTEFwNVFvXzdEeXRxM2x6ZUJEOEk4RldzZ0RoYVFIZQ?oc=5","urlToImage":null,"publishedAt":"2024-09-02T11:26:19Z","content":null},{"source":{"id":"google-news","name":"Google News"},"author":"Il Fatto Quotidiano","title":"Morta la bimba di 9 anni che fu rimpatriata con un volo militare dalla Thailandia dopo un interventoโ€ฆ - Il Fatto Quotidiano","description":null,"url":"https://news.google.com/rss/articles/CBMi9AFBVV95cUxQZzNZZTlVRTQxWkxiZFZrYnlvcWFFazY3aUFMNnAtT3pFYmlZSlhaU3Y1TEFsNktfdUJBNkFXWm9kOHNZZkN0Y2x6YlRjU2ZCY1BCSDY4T08wQ0RrMmJ2Uzhjd1ZhZnYwV1FVcUxINzBYR283dzBaN2JVSmNEQV90NW5nTXMwSzlfZmwteFkyVmtEQTVQdVY2VFpSVzFtOVhMVGZmRkxmbFB3V1N3SGUwb3JCWktrcEtjWjhnOWhZRXZ1R1FsY1FVXzVBcUZuU3ZUaUR0T2hkVXZYU3NzVzY4SmxCMTNxbjJoWWYwQmgwRXo2VDFV0gH6AUFVX3lxTE9KUjJycFRfQnA5V3FCN01FOVRXQllUMUJGbDhmb0JBLWp2eDloV1RhVkFkNjFPUnpTaTJGdC1uQVhhYzA1cElYcExna25Zc1FFN0xoNXRsVDlIOVFsZ0ZDTXRDX1R0NmRHX3dTd2E5YnhRZ1JUdzBQSk1oUkppMTIxMHdCbnEyTHZQZ24wWEZjRWlMZ1RKZkgwMjlaUFNuRUtubkdjeFBtVWRISDhfcWN3dzhPNy1XTjJKR085dWFmNUhPcmJ6NE52RVB3VVJlZFlaUGVCMVNrR2RGLThwOThPRVZZVmxZZWNfVUtxRjMxdTdBdnZjMGJNUHc?oc=5","urlToImage":null,"publishedAt":"2024-09-02T10:55:20Z","content":null},{"source":{"id":"google-news","name":"Google News"},"author":"Corriere della Sera","title":"Charles Leclerc, il bacio con la fidanzata Alexandra dopo la vittoria. Chi รจ la compagna da 1 milione di follower - Corriere della Sera","description":null,"url":"https://news.google.com/rss/articles/CBMipgJBVV95cUxQMm8tTlF2SjNrdGVleGtXWm11Y19ZZkFLSTBaNDgwUGllenlQNGZBVTNMOE4zQkdWak5RUnVkOFZjM2lUUmREZXdUamdNUXpDMnNYYlhCYXZkUVAxeHBNT0lmM2RueFRycXN1VHp6b3JFbS00NW1peFZVZFZHSlRoYVp6bjJNWHRMb2kyZl81NkRwUWt3LU44X0p1VGZQVVJFNHVwUGVuMTlVUGpudHR2WC1jZDVRV1pPUHJEVmljUHp4Vkw0R0ozaUFLbzlJUllONkVNUmxpS0dseGRFT290bzZXZmpsNV9QeWRVNXktVXJCY19CRGkwMGU0RExINTFGeGtENmN1WXVPZ3BnOVhwU3BmWWNYei1KRE1vRngtWmd6U2J2WWfSAasCQVVfeXFMTVlrQS1Sd1NWLVFYdzBQakxVUG9OMFdMWklXS2k5b09TX2FuM0RVOXo1Qk9pR2RMZ2tCcUlCNEVGX0JOaGY1RlE3YzZyS0pibnk1MGNTUFVyWFJPUWJMdEpZb0dHV1p1QjAwUUxIZlFlUXk3b2hIR1Z0cDJwUlVxd3hDOHdZb0g1TC10QTFoYkMwTkJXS1hObGlEeHFCaWp1a2NTNlhpZkpPU1QzX3dCWS1LMTBSQkcwWlNraWYyR3BaNmZrZTZLUl9ZTkZaXzd2d1hleTNwcnVrdEtJd2ttNjdMa0huY2ZvTnpWdjRnZDRKTFdmLUFBT2FReFdCc1M1ZVBpT2U5NTVIX3ItY0Q1ZTJ5NUl1X282Uk9qVHNDVmJHQjVxckNDcEZTcTA?oc=5","urlToImage":null,"publishedAt":"2024-09-02T10:38:54Z","content":null},{"source.. (๐Ÿคฅ redacted)
 - ๐Ÿค– [mode] ๐Ÿ’ฌ  Here are some of the top headlines in Italy:

* Teo Teocoli talks about Adriano Celentano: "We were very close friends, for five years he hasn't answered my phone calls anymore." - Corriere della Sera
* 9-year-old girl who was repatriated with a military flight from Thailand after surgery dies... - Il Fatto Quotidiano
* Charles Leclerc, the kiss with his girlfriend Alexandra after the victory. Who is the partner with 1 million followers - Corriere della Sera
* Israel, general strike underway: blocked roads and arrests. LIVE - Sky Tg24
* West Nile virus, first positive donor in the Cremona area - OglioPoNews
The end.
palladius commented 1 month ago

image

Shows the colorfulness.

palladius commented 1 month ago

Andrei if you like the idea I can change gem (from colorize to rainbow) and send a fix. You tell me

andreibondarev commented 1 month ago

Andrei if you like the idea I can change gem (from colorize to rainbow) and send a fix. You tell me

We're already using the rainbow gem!

palladius commented 1 month ago

Let me rephrase it. Would you like it if I add a generic pretty_print() for a GoogleMessage or better any LLM BaseMessage in a PR? If you find it silly or useless i wont spend that 30m doing it.