appchat 0.0.0

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.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 2f9959082fad1640186188cb5b51aa368261bd223f0b6de9064199c761131178
4
+ data.tar.gz: 7878632c1a40ec83858995d14a9ad9c138c914d5ebd992b7ca1e773b59087c23
5
+ SHA512:
6
+ metadata.gz: 12b74b31bc530a0118980c53fef319b06dce69a041be1d0e244985907a3db07495a6e74decaa2c75a7a0a2489eab8f32c4c2b8290c8e1451fa09442b74dcbf2a
7
+ data.tar.gz: 7c6816271a82c6c8e017d94b3c61ec268e6ec757e30174dc430728bc2f51238d145c76ef97650f03ce675246c285a35fe6fe6454d10cb300e8c7656b3ff8fab5
@@ -0,0 +1,83 @@
1
+ require 'rails/generators'
2
+ require 'rails/generators/migration'
3
+ require 'bundler'
4
+
5
+ class AppchatGenerator < Rails::Generators::Base
6
+ include Turbo::FramesHelper, ActionView::Helpers::TagHelper,
7
+ ActionView::Helpers::FormTagHelper, ActionView::Helpers::FormHelper, Rails.application.routes.url_helpers
8
+ source_root File.expand_path('templates', __dir__)
9
+
10
+ def add_gems
11
+ unless gem_exists?('ollama-ai')
12
+ append_to_file 'Gemfile', "\ngem 'ollama-ai'\n"
13
+ end
14
+
15
+ unless gem_exists?('tailwindcss-rails')
16
+ append_to_file 'Gemfile', "\ngem 'tailwindcss-rails'\n"
17
+ end
18
+
19
+ Bundler.with_unbundled_env do
20
+ run 'bundle install'
21
+ end
22
+ run 'rails tailwindcss:install'
23
+ end
24
+
25
+ def generate_scaffolds
26
+ generate "model", "Chat"
27
+ generate "scaffold", "Message chat:references content:text role:integer"
28
+ end
29
+
30
+ def create_views
31
+ copy_file "chats_controller.rb", "app/controllers/chats_controller.rb"
32
+ copy_file "chats/chat.html.erb", "app/views/chats/_chat.html.erb", force: true
33
+ copy_file "chats/index.html.erb", "app/views/chats/index.html.erb", force: true
34
+ copy_file "chats/show.html.erb", "app/views/chats/show.html.erb", force: true
35
+ copy_file "messages/index.html.erb", "app/views/messages/index.html.erb", force: true
36
+ copy_file "messages/new.html.erb", "app/views/messages/new.html.erb", force: true
37
+ copy_file "messages/message.html.erb", "app/views/messages/_message.html.erb", force: true
38
+ copy_file "javascript/chat_message_controller.js", "app/javascript/controllers/chat_message_controller.js"
39
+ end
40
+
41
+ def copy_models
42
+ copy_file "models/message.rb", "app/models/message.rb", force: true
43
+ copy_file "models/chat.rb", "app/models/chat.rb", force: true
44
+ end
45
+
46
+ def set_associations
47
+ inject_into_class 'app/models/chat.rb', 'Chat', " has_many :messages, dependent: :destroy\n"
48
+ end
49
+
50
+ def run_migrations
51
+ rake "db:migrate"
52
+ end
53
+
54
+ def create_background_job
55
+ copy_file "get_ai_response_job.rb", "app/jobs/get_ai_response_job.rb"
56
+ end
57
+
58
+ def create_messages_controller
59
+ copy_file "messages_controller.rb", "app/controllers/messages_controller.rb", force: true
60
+ end
61
+
62
+ def show_art
63
+ puts <<-ART
64
+
65
+ _ _
66
+ | | | |
67
+ __ _ _ __ _ __ ___ | |__ __ _ | |_
68
+ / _` || '_ \ | '_ \ / __|| '_ \ / _` || __|
69
+ | (_| || |_) || |_) || (__ | | | || (_| || |_
70
+ \__,_|| .__/ | .__/ \___||_| |_| \__,_| \__|
71
+ | | | |
72
+ |_| |_|
73
+
74
+ ART
75
+ end
76
+
77
+ private
78
+
79
+ def gem_exists?(gem_name)
80
+ File.read('Gemfile').include? gem_name
81
+ end
82
+ end
83
+
@@ -0,0 +1,5 @@
1
+ <%= link_to chat, data: { turbo_frame: :chat } do %>
2
+ <div class="w-full text-gray-100 hover:text-green-500">
3
+ <%= chat&.messages&.first&.content%>
4
+ </div>
5
+ <% end %>
@@ -0,0 +1,22 @@
1
+ <style>
2
+ body {
3
+ background-color: black;
4
+ }
5
+ </style>
6
+ <div class="flex w-full">
7
+ <%= turbo_stream_from :chats %>
8
+ <div class="max-w-sm w-full flex flex-col gap-4 p-2 w-full flex-shrink-0 bg-[#2e2e2e] rounded-lg" id="chats">
9
+ <%= link_to chats_path, data: { turbo_method: :post, turbo_frame: :chat }, class: "flex gap-2 justify-center items-center bg-gray-500 text-gray-100 rounded-lg p-2 text-center mr-auto" do %>
10
+ <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="size-6">
11
+ <path stroke-linecap="round" stroke-linejoin="round" d="M12 4.5v15m7.5-7.5h-15" />
12
+ </svg>
13
+ <span> Create Chat </span>
14
+ <% end %>
15
+ <% @chats.each do |chat| %>
16
+ <%= render "chat", chat: chat %>
17
+ <% end %>
18
+ </div>
19
+ <div class="w-full ml-4">
20
+ <%= turbo_frame_tag :chat, src: ( chat_path(@chats.first) if @chats.any? ) %>
21
+ </div>
22
+ </div>
@@ -0,0 +1,7 @@
1
+ <%= turbo_frame_tag :chat do %>
2
+ <div class="flex flex-col w-full h-full">
3
+ <%= turbo_stream_from(dom_id(@chat, :messages)) %>
4
+ <%= turbo_frame_tag(:messages, src: messages_path(chat_id: @chat.id)) %>
5
+ <%= turbo_frame_tag(:new_message, src: new_message_path(chat_id: @chat.id)) %>
6
+ </div>
7
+ <% end %>
@@ -0,0 +1,12 @@
1
+ class ChatsController < ApplicationController
2
+ def show
3
+ @chat = Chat.find(params[:id])
4
+ end
5
+ def index
6
+ @chats = Chat.all
7
+ end
8
+ def create
9
+ @chat = Chat.create
10
+ redirect_to @chat
11
+ end
12
+ end
@@ -0,0 +1,36 @@
1
+ class GetAiResponseJob < ApplicationJob
2
+ queue_as :default
3
+
4
+ attr_reader :chat, :user_prompt
5
+
6
+ def perform(chat_id, user_prompt)
7
+ @chat = Chat.find(chat_id)
8
+ @user_prompt = user_prompt
9
+ call_ollama
10
+ end
11
+
12
+ private
13
+
14
+ def call_ollama
15
+ client = Ollama.new(
16
+ credentials: { address: 'http://localhost:11434' },
17
+ options: { server_sent_events: true }
18
+ )
19
+ message = chat.messages.create(role: 'assistant')
20
+
21
+ response = client.generate(
22
+ {
23
+ model: 'llama3.1',
24
+ prompt: user_prompt,
25
+ stream: true,
26
+ }
27
+ ) do |event, raw|
28
+ if event["response"]
29
+ new_content = ''
30
+ new_content += message.content if message.content
31
+ new_content += event["response"] if event["response"]
32
+ message.update(content: new_content)
33
+ end
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,7 @@
1
+ import { Controller } from "@hotwired/stimulus"
2
+ export default class extends Controller {
3
+ static targets = ["message"]
4
+ messageTargetConnected() {
5
+ this.element.scrollTop = this.element.scrollHeight
6
+ }
7
+ }
@@ -0,0 +1,5 @@
1
+ <%= turbo_frame_tag(:messages) do %>
2
+ <div data-controller="chat-message" class="w-full gap-4 flex flex-col h-[70vh] overflow-y-scroll" id="chat-messages">
3
+ <%= render partial: "message", collection: @messages %>
4
+ </div>
5
+ <% end %>
@@ -0,0 +1,3 @@
1
+ <div data-chat-message-target="message" id="<%= dom_id(message) %>" class="bg-gray-200 text-gray-900 shadow-lg p-4 rounded-lg">
2
+ <%= message.content %>
3
+ </div>
@@ -0,0 +1,16 @@
1
+ <%= turbo_frame_tag :new_message do %>
2
+ <%= form_with model: @chat.messages.new, url: messages_path(chat_id: @chat.id) do |f| %>
3
+ <div class="w-full flex items-center gap-2">
4
+ <div class="flex flex-col w-full">
5
+ <%= f.label :content, "What do you want to ask?" %>
6
+ <%= f.text_area :content, class: "w-full" %>
7
+ </div>
8
+ <%= button_tag class: "mt-4 flex p-2 rounded-lg bg-gradient-to-r from-indigo-500 to-blue-500 text-blue-100 font-semibold" do %>
9
+ Send Message
10
+ <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="size-6">
11
+ <path stroke-linecap="round" stroke-linejoin="round" d="M6 12 3.269 3.125A59.769 59.769 0 0 1 21.485 12 59.768 59.768 0 0 1 3.27 20.875L5.999 12Zm0 0h7.5" />
12
+ </svg>
13
+ <% end %>
14
+ </div>
15
+ <% end %>
16
+ <% end %>
@@ -0,0 +1,32 @@
1
+ class MessagesController < ApplicationController
2
+ before_action :set_chat
3
+
4
+ def new
5
+ @message = @chat.messages.new
6
+ end
7
+
8
+ def create
9
+ @message = @chat.messages.build(message_params)
10
+ if @message.save
11
+ GetAiResponseJob.perform_later(@message.chat_id, @message.content)
12
+ redirect_to new_message_path(chat_id: @chat.id), notice: 'Message was successfully created.'
13
+ else
14
+ render :new
15
+ end
16
+ end
17
+
18
+ def index
19
+ @messages = @chat.messages
20
+ end
21
+
22
+ private
23
+
24
+ def set_chat
25
+ @chat = Chat.find(params[:chat_id])
26
+ end
27
+
28
+ def message_params
29
+ params.require(:message).permit(:content, :role)
30
+ end
31
+ end
32
+
@@ -0,0 +1,8 @@
1
+ class Chat < ApplicationRecord
2
+ has_many :messages, dependent: :destroy
3
+ after_create_commit :broadcast_chat
4
+
5
+ def broadcast_chat
6
+ broadcast_append_to(:chats, target: "chats", partial: "chats/chat", locals: { chat: self })
7
+ end
8
+ end
@@ -0,0 +1,14 @@
1
+ class Message < ApplicationRecord
2
+ include ActionView::RecordIdentifier
3
+ belongs_to :chat
4
+ after_create_commit :broadcast_message
5
+ after_update_commit :broadcast_update_message
6
+
7
+ def broadcast_update_message
8
+ broadcast_replace_to dom_id(chat, :messages), target: dom_id(self), partial: "messages/message", locals: { message: self }
9
+ end
10
+
11
+ def broadcast_message
12
+ broadcast_append_to dom_id(chat, :messages), target: "chat-messages", partial: "messages/message", locals: { message: self }
13
+ end
14
+ end
metadata ADDED
@@ -0,0 +1,111 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: appchat
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.0
5
+ platform: ruby
6
+ authors:
7
+ - hackliteracy
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2024-08-06 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '2.0'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '2.0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '12.0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '12.0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rails
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '6.0'
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '6.0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: ollama-ai
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: 1.3.0
62
+ type: :runtime
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: 1.3.0
69
+ description: The best and easiest framework for adding chats
70
+ email: hackliteracy@gmail.com
71
+ executables: []
72
+ extensions: []
73
+ extra_rdoc_files: []
74
+ files:
75
+ - lib/generators/appchat/appchat_generator.rb
76
+ - lib/generators/appchat/templates/chats/chat.html.erb
77
+ - lib/generators/appchat/templates/chats/index.html.erb
78
+ - lib/generators/appchat/templates/chats/show.html.erb
79
+ - lib/generators/appchat/templates/chats_controller.rb
80
+ - lib/generators/appchat/templates/get_ai_response_job.rb
81
+ - lib/generators/appchat/templates/javascript/chat_message_controller.js
82
+ - lib/generators/appchat/templates/messages/index.html.erb
83
+ - lib/generators/appchat/templates/messages/message.html.erb
84
+ - lib/generators/appchat/templates/messages/new.html.erb
85
+ - lib/generators/appchat/templates/messages_controller.rb
86
+ - lib/generators/appchat/templates/models/chat.rb
87
+ - lib/generators/appchat/templates/models/message.rb
88
+ homepage: https://rubygems.org/gems/appchat
89
+ licenses:
90
+ - MIT
91
+ metadata: {}
92
+ post_install_message:
93
+ rdoc_options: []
94
+ require_paths:
95
+ - lib
96
+ required_ruby_version: !ruby/object:Gem::Requirement
97
+ requirements:
98
+ - - ">="
99
+ - !ruby/object:Gem::Version
100
+ version: '3.0'
101
+ required_rubygems_version: !ruby/object:Gem::Requirement
102
+ requirements:
103
+ - - ">="
104
+ - !ruby/object:Gem::Version
105
+ version: '0'
106
+ requirements: []
107
+ rubygems_version: 3.5.11
108
+ signing_key:
109
+ specification_version: 4
110
+ summary: Appchat makes it easy to add a chat to your app
111
+ test_files: []