]> gitweb.mndrdr.org Git - arelpe.git/commitdiff
Added the ability to send posts to summariser (not currently av. outside the admin...
authorAidan Cornelius-Bell <[email protected]>
Sun, 8 Dec 2024 06:43:21 +0000 (17:13 +1030)
committerAidan Cornelius-Bell <[email protected]>
Sun, 8 Dec 2024 06:43:21 +0000 (17:13 +1030)
app/assets/stylesheets/application.css
app/controllers/posts_controller.rb
app/services/kagi_summarizer_service.rb [new file with mode: 0644]
app/views/posts/_post.html.erb
app/views/posts/index.html.erb
app/views/posts/show.html.erb
config/credentials.yml.enc
config/routes.rb
db/migrate/20241208061729_add_summary_to_posts.rb [new file with mode: 0644]
db/schema.rb

index 0332ca8d2214cb641ac7bac1081876a3918f7d26..4f0692b4ef4410354ee0ab15ebcfce7b5a7fd1e6 100644 (file)
@@ -535,6 +535,10 @@ input[type="submit"],
     font-size: 0.875rem;
 }
 
+.button.summary {
+    margin-top: 5px;
+}
+
 .button.danger {
     background-color: #dc3545;
     color: var(--body-text);
index 1c6685c1cdcb6312e782fc70904472ff6d4b88bb..ef1d82b5048b44654b3b14748a97584d967af9a6 100644 (file)
@@ -120,6 +120,53 @@ class PostsController < ApplicationController
     redirect_to posts_path
   end
 
+  def summarize
+    @post = Post.find(params[:id])
+    Rails.logger.debug "Attempting to summarize post #{@post.id} (#{@post.post_type})"
+
+    summarizer = KagiSummarizerService.new
+
+    # Determine what content to summarize based on post type
+    content_to_summarize = if @post.bookmark? && @post.url.present?
+      Rails.logger.debug "Using URL for summarization: #{@post.url}"
+      @post.url
+    elsif @post.content.present?
+      Rails.logger.debug "Using content for summarization (first 100 chars): #{@post.content.truncate(100)}"
+      @post.content
+    else
+      Rails.logger.warn "No content available for summarization"
+      nil
+    end
+
+    if content_to_summarize.nil?
+      redirect_to @post, alert: 'No content or URL available to summarize.'
+      return
+    end
+
+    type = @post.bookmark? && @post.url.present? ? :url : :text
+    result = summarizer.summarize(content_to_summarize, type)
+
+    Rails.logger.debug "Summarization result: #{result.inspect}"
+
+    if result && result['output'].present?
+      success = @post.update(summary: result['output'])
+      Rails.logger.debug "Update post with summary: #{success ? 'successful' : 'failed'}"
+      if success
+        redirect_to @post, notice: 'Summary generated successfully.'
+      else
+        Rails.logger.error "Failed to save summary: #{@post.errors.full_messages}"
+        redirect_to @post, alert: "Failed to save summary: #{@post.errors.full_messages.join(', ')}"
+      end
+    else
+      error_message = if result
+        "API returned success but no summary output was present"
+      else
+        "Failed to generate summary from API"
+      end
+      Rails.logger.error error_message
+      redirect_to @post, alert: error_message
+    end
+  end
 
   private
     # Use callbacks to share common setup or constraints between actions.
diff --git a/app/services/kagi_summarizer_service.rb b/app/services/kagi_summarizer_service.rb
new file mode 100644 (file)
index 0000000..318dd8c
--- /dev/null
@@ -0,0 +1,47 @@
+class KagiSummarizerService
+  include HTTParty
+  base_uri 'https://kagi.com/api/v0'
+
+  def initialize
+    @options = {
+      headers: {
+        'Authorization': "Bot #{Rails.application.credentials.kagi[:api_key]}",
+        'Content-Type': 'application/json'
+      }
+    }
+    Rails.logger.debug "KagiSummarizerService initialized with options: #{@options.inspect}"
+  end
+
+  def summarize(content, type = :text)
+    Rails.logger.debug "Summarizing #{type} content: #{content.truncate(100)}"
+
+    body = if type == :url
+      {
+        url: content,
+        engine: 'agnes',
+        summary_type: 'summary'
+      }
+    else
+      {
+        text: content,
+        engine: 'agnes',
+        summary_type: 'summary'
+      }
+    end
+
+    Rails.logger.debug "Sending request to Kagi API with body: #{body.inspect}"
+
+    response = self.class.post('/summarize', @options.merge(body: body.to_json))
+    Rails.logger.debug "Received response from Kagi API: Status #{response.code}, Body: #{response.body}"
+
+    if response.success?
+      parsed_response = JSON.parse(response.body)
+      Rails.logger.debug "Parsed response: #{parsed_response.inspect}"
+      parsed_response
+    else
+      Rails.logger.error "Kagi API error: #{response.code} - #{response.body}"
+      Rails.logger.error "Full response object: #{response.inspect}"
+      nil
+    end
+  end
+end
index c9a94079642ab14529d7af4b533370b973abe9fe..fff5bb92929f40d0b49df75065b8db5e3f364c36 100644 (file)
     <%= post.tags %>
   </p>
 
+  <p>
+    <strong>Summary:</strong>
+    <%= post.summary %>
+  </p>
+
   <p>
     <strong>Content:</strong>
-    <%= post.content %>
+    <%= if post&.content? then post.rendered_content.html_safe else "No content." end %>
   </p>
 
   <p>
index 70da4e4c941a64a607ca57d0c81c2cb7dd078f3f..9a58f61aaadd5113e744912ce5a03fa1751826c7 100644 (file)
     <table>
       <thead>
         <tr>
-          <th>Title</th>
-          <th>Type</th>
-          <th>Created</th>
-          <th>Tags</th>
-          <th>Actions</th>
+          <th style="width: 50%;">Title</th>
+          <th style="width: 10%;">Type</th>
+          <th style="width: 10%;">Created</th>
+          <th style="width: 10%;">Tags</th>
+          <th style="width: 20%;">Actions</th>
         </tr>
       </thead>
       <tbody>
@@ -29,6 +29,7 @@
               <%= link_to "View", post, class: "button small" %>
               <%= link_to "Edit", edit_post_path(post), class: "button small" %>
               <%= link_to "Delete", post, method: :delete, data: { confirm: "Are you sure you want to delete this post?" }, class: "button small danger" %>
+              <%= button_to "Generate Summary", summarize_post_path(post), class: "button small summary", data: { confirm: 'This will call the Kagi API. Continue?' } %>
             </td>
           </tr>
         <% end %>
@@ -41,4 +42,4 @@
   <div class="container">
     <%= paginate @posts %>
   </div>
-<% end %>
\ No newline at end of file
+<% end %>
index 739d9cfb77fd3993bafb1b1e87efffe73b0588c3..2f00e086f7b0533b578af1c9b2ed32d3bee62f52 100644 (file)
@@ -3,12 +3,12 @@
   <%= link_to "Back to posts", posts_path, class: "button" %>
 </div>
 <div class="post">
-  <div class="container">    
+  <div class="container">
     <%= render @post %>
-    
+
     <div>
       <%= link_to "Edit this post", edit_post_path(@post), class: "button" %>
-    
+      <%= button_to "Summarise this post", summarize_post_path(@post), class: "button" %>
       <%= button_to "Destroy this post", @post, method: :delete %>
     </div>
   </div>
index 19f60ef0c4a4a9f119a7aa7ba3bf34a80fec195f..f16cdbec84d13a81520d14a8be1e819a36534039 100644 (file)
@@ -1 +1 @@
-R6pLqAgOKbr+y07Is0RC9w3wQKbkr2h2KZO4RNpGCPAaE+X9ZK6i3AdB0XYfDiBRfvtj05EhYDJ+Yr72985yeeRhnppVqkwNK1mWp+SGfY+KVvaKI7HFYG8igI0LthDAdsyeoA2+ElpZgjHCCLqz36gRKSY/KEbT/y0NukHdQRzsWFHwqgY85vQK9gRfDBpM72h4iPwb9TOPvMtJuVwfaIAdcDY0OqaQpTlFIGjh/bT9njHuO2h4mJ6dCBJYoFR0+8oCpd8hHWHtxeB4bsqKspfxrNvFTYEDQUnNwJEbQGNl14577rhEshQ2WfgUVFGzTzfEpzQmFZZJtnWhJuJbgVaxUwH5STUKWEWNY5/gD2vgp1oj0aUO6eiyOjz5YCkUieR2RV3hVF+yvOMb9NTt2EBYjJGeoqngzKi/Hq0xnLHIRmkoFHPvuC1RHn0Ucg1Nez4cmWppoOK3xm/b0H2lKsWi97vkkii38lqtfmmRFtsdXf4AvFOQ2NWpFlLKLwHT87/bU32XIzPObwErw/wv9irxrBMAlDDqOTqtqd6k3liddoNGCqUqHLxSC0IoH/G2tdg1PzoKBvtIVyjtctYtUnta1vgjpz727WCSSYO6gDTOxTkRmwc++DcBAzOJFkYSz8gFm02TjHaBhzXQeqw=--fmjiwM3a6xuvqqTn--wwZXJd1Zcs5AJV/lQbpCtw==
\ No newline at end of file
+v2C864ebli2Zlrpg1eDeEn17NBNNghNeT86hcfSfebENXaStabVwZbEfgHTryFxZcISmAZE4rjjdcJcFSqTNQwvUvLGWaT3efR8WyZ2QQP14OSwL8+hnHDpDXLJrQIDUOHFF+aLaN0/uh3UPbFkBIf6eYyDVO+PP3jxb5bXsNC5wkqiCA/gBDuZoCLGrX9Pnw2nPWcXptVV2H2PVcQOaJDUcJl4yFJBSU3/cV/f9yFPV70cfrqUxU5hSHxHqfSZUF9bh/A6AAkvVWBOgJIETA3DiIS0fvoMSRK5uQuDWsaY7fdc947QXw4VrdvFSQqAegzzDjNYgLtZIqQ2GHDhaRWnmsVGf7IqA/6tKb6jGIc0G/Y7Mtdoa4s177dAdrMaIr+PM4ZMMbACYq1WbQWZ1IfMttyId0tAlRRlVbAFPOhFxElCHEWWlq1t3xGwgFDQOyfzX3P2Cr1FCeVXJb8VwGz32CceOna6BnhzRns6mQKt6VI+uAh6T2Uoe+krtM1jb6XT5+u0qZ8jo9P/iibCeeBZr9JBQ4rE+8AIvHOIZNuq7nZQDAHL+s9WtVrkvVjpRQ28dpccbjyQFvXhjqFUFIVGDTITi31FaHcjNBMhZyMKLtv/c9ASojRFrkBoDTgulGq8v+uEnW/3HPNkW+X3fqRXtjt1URKS+Qz57J7JOWt/EvX/f7PCG--pBijWvzkta+/36PZ--LnhGLSczKJbXJk9B8MyGRQ==
\ No newline at end of file
index 9df6e47fc16393c4c18f1ad27e335c2786bc5f2b..f4dcd09e54fa7cd58d888b6244d1353cc735ede0 100644 (file)
@@ -9,7 +9,7 @@ Rails.application.routes.draw do
       resources :pages, only: [:index, :show]
     end
   end
-  
+
   resources :mailing_lists, only: [:index] do
     collection do
       post 'subscribe'
@@ -29,14 +29,20 @@ Rails.application.routes.draw do
   get 'export', to: 'posts#export'
   post 'import', to: 'posts#import'
   resources :api_keys
-  devise_for :users, controllers: { 
-    registrations: 'users/registrations', 
+  devise_for :users, controllers: {
+    registrations: 'users/registrations',
     confirmations: 'users/confirmations',
     sessions: 'users/sessions'
   }
   get 'users/two_factor_authentication', to: 'users/two_factor_authentication#show'
   post 'users/two_factor_authentication', to: 'users/two_factor_authentication#create'
-  resources :posts
+
+  resources :posts do
+    member do
+      post :summarize
+    end
+  end
+
   get '/feed', to: 'pubview#rss', as: 'rss', defaults: { format: 'rss' }
   get '/feed/dispatches', to: 'pubview#dispatches_rss', as: 'dispatches_rss', defaults: { format: 'rss' }
   get '/join', to: "pubview#join"
diff --git a/db/migrate/20241208061729_add_summary_to_posts.rb b/db/migrate/20241208061729_add_summary_to_posts.rb
new file mode 100644 (file)
index 0000000..6efb25e
--- /dev/null
@@ -0,0 +1,5 @@
+class AddSummaryToPosts < ActiveRecord::Migration[7.2]
+  def change
+    add_column :posts, :summary, :text
+  end
+end
index ddc1cd4166e435b6954b40d9c582ecddf8aeaab5..ffb94b52f3c83f1f5a8891a94e834cf814d777c6 100644 (file)
@@ -10,7 +10,7 @@
 #
 # It's strongly recommended that you check this file into your version control system.
 
-ActiveRecord::Schema[7.2].define(version: 2024_10_09_212849) do
+ActiveRecord::Schema[7.2].define(version: 2024_12_08_061729) do
   create_table "api_keys", charset: "utf8mb4", collation: "utf8mb4_0900_ai_ci", force: :cascade do |t|
     t.string "key"
     t.datetime "created_at", null: false
@@ -38,6 +38,7 @@ ActiveRecord::Schema[7.2].define(version: 2024_10_09_212849) do
     t.string "url"
     t.datetime "created_at", null: false
     t.datetime "updated_at", null: false
+    t.text "summary"
     t.index ["post_type"], name: "index_posts_on_post_type"
     t.index ["published_at"], name: "index_posts_on_published_at"
     t.index ["slug"], name: "index_posts_on_slug", unique: true