appchat 0.0.0

Sign up to get free protection for your applications and to get access to all the features.
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: []