_binary diff --git a/src/configs/Config.php b/src/configs/Config.php
index 8035d8a40..44b9d4195 100755
--- a/src/configs/Config.php
+++ b/src/configs/Config.php
@@ -354,6 +354,10 @@ nsdefine('ONE_HOUR', 3600);
 nsdefine('ONE_MINUTE', 60);
 /** Number of seconds in a second */
 nsdefine('ONE_SECOND', 1);
+/** URL endpoint for LLM API service used for AI summarization */
+nsdefine('LLM_API_URL', "http://localhost:1234/v1/chat/completions");
+/** Model name to use for LLM API requests */
+nsdefine('LLM_MODEL', "aya-23-8b");
 /** Whether to use conjunctive search queries or disjunctive */
 nsconddefine('USE_CONJUNCTIVE_QUERY', false);
 /** setting Profile.php to something else in LocalConfig.php allows one to have
diff --git a/src/controllers/ApiController.php b/src/controllers/ApiController.php
index a9a20a63a..e675ddf96 100644
--- a/src/controllers/ApiController.php
+++ b/src/controllers/ApiController.php
@@ -51,6 +51,11 @@ class ApiController extends Controller implements CrawlConstants
      * @var array
      */
     public static $component_activities = [  "social" => ["wiki"] ];
+    /**
+     * These are the activities supported by this controller
+     * @var array
+     */
+    public $activities = ["summarize"];
     /**
      * Used to process requests related to user group activities outside of
      * the admin panel setting. This either could be because the admin panel
@@ -117,4 +122,110 @@ class ApiController extends Controller implements CrawlConstants
         }
         return $data;
     }
+    /**
+     * Used to get the messages for a given thread id.
+     *
+     * @param string $thread_id The id of the thread to get messages for.
+     * @return array $messages containing the messages for the thread
+     */
+    private function getMessages($thread_id)
+    {
+        $group_model = $this->model("group");
+        $user_id = isset($_SESSION['USER_ID']) ?
+            $_SESSION['USER_ID'] : C\PUBLIC_USER_ID;
+        $search_array = [ ["parent_id", "=", $thread_id, ""] ];
+        $limit = 0;
+        $results_per_page = 10000;
+        // -2 is just_thread case
+        $for_group = -2;
+        $sort = "ksort";
+        $messages = $group_model->getGroupItems($limit, $results_per_page,
+            $search_array, $user_id, $for_group);
+        return $messages;
+    }
+    /**
+     * Handles a request to summarize a thread using the LLM.
+     *
+     * Expected parameters:
+     * - thread_id: The id of the thread to summarize.
+     *
+     * @return array $data containing summary results and status
+     */
+    public function summarize()
+    {
+        $data = [];
+        $data['ELEMENT'] = 'summarize';
+        if (empty($_REQUEST['thread_id'])) {
+            $data['ERRORS'] = ["Missing parameter - 'thread_id' required"];
+            return $data;
+        }
+        $thread_id = $this->clean($_REQUEST['thread_id'], "string");
+        $messages = $this->getMessages($thread_id);
+        if (empty($messages)) {
+            $data['ERRORS'] = ["No messages found for thread id $thread_id"];
+            return $data;
+        }
+        $text = "";
+        foreach ($messages as $msg) {
+            $pretty_date = date("r", $msg['PUBDATE']);
+            $username = $msg['USER_NAME'];
+            $content = $msg['DESCRIPTION'];
+            $text .= "On {$pretty_date}, {$username} wrote: \"{$content}\"\n\n";
+        }
+        $summarize_prompt = "Summarize the following thread concisely, "
+            . "capturing the key points:\n". "<in>" . $text . "</in>\n"
+            . "Output the summary between <out></out> tags. "
+            . "Do not include any extra commentary.";
+        $api_url = C\LLM_API_URL;
+        $model = C\LLM_MODEL;
+        $request_body = [
+            "model" => $model,
+            "messages" => [
+                ["role" => "system", "content" => "You are a helpful assistant "
+                . "that summarizes threads concisely."],
+                ["role" => "user", "content" => $summarize_prompt]
+            ],
+            "temperature" => 0.1,
+            "max_tokens" => -1,
+            "stream" => false
+        ];
+        $result = $this->sendLLMRequest($api_url, $request_body);
+        if (!$result) {
+            $data['ERRORS'] = ["Failed to connect to summarization service"];
+        } else {
+            $result_obj = json_decode($result, true);
+            if (isset($result_obj['choices'][0]['message']['content'])) {
+                $content = $result_obj['choices'][0]['message']['content'];
+                preg_match('/<out>([\s\S]*?)<\/out>/', $content, $matches);
+                if (isset($matches[1])) {
+                    $data['SUMMARY'] = trim($matches[1]);
+                    $data['STATUS'] = 'success';
+                } else {
+                    $data['ERRORS'] = ["Summary format not recognized"];
+                }
+            } else {
+                $data['ERRORS'] = ["Invalid response from LLM"];
+            }
+        }
+        return $data;
+    }
+    /**
+     * Helper method to send API requests to LLM service
+     *
+     * @param string $url The API endpoint URL
+     * @param array $data The request data to send
+     * @return string|bool The response body or false on failure
+     */
+    private function sendLLMRequest($url, $data)
+    {
+        $post_data = json_encode($data);
+        $headers = ['Content-Type: application/json'];
+        $response = L\FetchUrl::getPage($url, $post_data, true, null, 
+            C\SINGLE_PAGE_TIMEOUT, $headers);
+        if ($response === false) {
+            error_log("LLM API request failed");
+            return false;
+        }
+        return $response;
+    }
 }
diff --git a/src/controllers/components/Component.php b/src/controllers/components/Component.php
index 460ca785a..8412c6264 100644
--- a/src/controllers/components/Component.php
+++ b/src/controllers/components/Component.php
@@ -158,6 +158,9 @@ class Component
                 tl('wiki_js_resource_description').'", '.
                 'wiki_element_list_icon :"'. tl('wiki_element_list_icon').'",'.
                 'wiki_element_grid_icon :"'. tl('wiki_element_grid_icon').'",'.
+                'wiki_js_summarizing :"'. tl('wiki_js_summarizing').'",'.
+                'wiki_js_summary_unavailable :"'.
+                tl('wiki_js_summary_unavailable').'",'.
                 'wiki_js_render_engine:"'.
                     ($data['RENDER_ENGINE'] ?? 'mediawiki') .'",'.
                 '};';
diff --git a/src/locale/en_US/configure.ini b/src/locale/en_US/configure.ini
index 213df545a..a215727e5 100644
--- a/src/locale/en_US/configure.ini
+++ b/src/locale/en_US/configure.ini
@@ -5633,6 +5633,7 @@ iconlink_helper_join_groups = "Join Groups"
 iconlink_helper_leave_group = "Leave Group"
 iconlink_helper_localize = "Localize"
 iconlink_helper_manage_machines = "Manage Machines"
+iconlink_helper_ai_summary = "Summarize Thread"
 iconlink_helper_manage_mixes = "Manage Mixes"
 iconlink_helper_messages = "Messages"
 iconlink_helper_group_pages = "Pages"
diff --git a/src/scripts/wiki.js b/src/scripts/wiki.js
index 3129ff81a..32d9eb37a 100755
--- a/src/scripts/wiki.js
+++ b/src/scripts/wiki.js
@@ -934,3 +934,41 @@ function addToPage(resource_name, textarea_id, sub_path)
          split_adjuster.addEventListener('mousedown', mouseDownHandler);
      }
  });
+
+ function toggleAISummary(csrfToken, baseUrl, summaryId) {
+    var summaryBox = document.getElementById("ai-summary-" + summaryId);
+    if (!summaryBox) return;
+    if (summaryBox.style.display === "none" || summaryBox.style.display === "") {
+        summaryBox.style.display = "block";
+        summaryBox.innerHTML = "<p>" + tl['wiki_js_summarizing'] + "</p>";
+        var url = baseUrl + "?thread_id=" + encodeURIComponent(summaryId) +
+            "&c=api&a=summarize&YIOOP_TOKEN=" + encodeURIComponent(csrfToken);
+        fetch(url, { method: "POST", headers: {
+                "User-Agent": "Yioop-Web-Client/1.0",
+                "Content-Type": "application/x-www-form-urlencoded"},
+            credentials: "include"
+        })
+        .then(function(response) {
+            if (!response.ok) {
+                throw new Error("HTTP error! Status: " + response.status);
+            }
+            return response.json();
+        })
+        .then(function(data) {
+            if (data.SUMMARY) {
+                summaryBox.innerHTML = "<p>" + data.SUMMARY + "</p>";
+            } else if (data.ERRORS) {
+                summaryBox.innerHTML = "<p>" + data.ERRORS.join(", ") + "</p>";
+            } else {
+                summaryBox.innerHTML = "<p>" + tl['wiki_js_summary_unavailable']
+                + "</p>";
+            }
+        })
+        .catch(function() {
+            summaryBox.innerHTML = "<p>" + tl['wiki_js_summary_unavailable']
+                + "</p>";
+        });
+    } else {
+      summaryBox.style.display = "none";
+    }
+  }
diff --git a/src/views/ApiView.php b/src/views/ApiView.php
index 75d35314d..afd074e11 100644
--- a/src/views/ApiView.php
+++ b/src/views/ApiView.php
@@ -65,6 +65,10 @@ class ApiView extends View
                     $data['API'] = true;
                     $this->element("groupfeed")->render($data);
                     break;
+                case 'summarize':
+                    $data['API'] = true;
+                    $this->element("api")->render($data);
+                    break;
                 case 'usermessages':
                     $data['API'] = true;
                     header("X-Accel-Buffering: no");
diff --git a/src/views/elements/ApiElement.php b/src/views/elements/ApiElement.php
index 10a9a6eea..cd11a8f1b 100644
--- a/src/views/elements/ApiElement.php
+++ b/src/views/elements/ApiElement.php
@@ -55,7 +55,11 @@ class ApiElement extends Element implements CrawlConstants
         $logged_in = isset($data["ADMIN"]) && $data["ADMIN"];
         $can_edit = $logged_in && isset($data["CAN_EDIT"]) &&
             $data["CAN_EDIT"];
-        $this->renderJsonDocument($data, $can_edit, $logged_in);
+            if (isset($data['ELEMENT']) && $data['ELEMENT'] == 'summarize') {
+                $this->renderSummarizeResponse($data);
+            } else {
+                $this->renderJsonDocument($data, $can_edit, $logged_in);
+            }
     }
     /**
      * Used to send a Wiki content response for reading. If the page does
@@ -108,4 +112,30 @@ class ApiElement extends Element implements CrawlConstants
         e(json_encode($out_array));
         L\webExit();
     }
+    /**
+     * Used to send a Summarize API response
+     *
+     * @param array $data fields containing translation results
+     */
+    public function renderSummarizeResponse($data)
+    {
+        $out_array = [];
+        $http_code = "500 Internal Server Error";
+        if (isset($data['SUMMARY'])) {
+            $out_array["SUMMARY"] = $data['SUMMARY'];
+            $out_array["STATUS"] = $data['STATUS'] ?? 'success';
+            $http_code = "200 OK";
+        } else {
+            $http_code = "400 Bad Request";
+        }
+        if (isset($data['ERRORS']) && count($data['ERRORS']) > 0) {
+            $out_array['ERRORS'] = $data['ERRORS'];
+            $http_code = "400 Bad Request";
+        }
+        $web_site = $this->view->controller_object->web_site;
+        $web_site->header("Content-Type: application/json");
+        $web_site->header("HTTP/1.1 " . $http_code);
+        e(json_encode($out_array));
+        L\webExit();
+    }
 }
diff --git a/src/views/elements/GroupfeedElement.php b/src/views/elements/GroupfeedElement.php
index bddeb4092..bf6cba5c4 100644
--- a/src/views/elements/GroupfeedElement.php
+++ b/src/views/elements/GroupfeedElement.php
@@ -177,6 +177,7 @@ class GroupfeedElement extends Element implements CrawlConstants
         $is_api = !empty($data['API']);
         $is_status = !empty($data['STATUS']);
         $open_in_tabs = $data['OPEN_IN_TABS'];
+        $icon_helper = $this->view->helper('iconlink');
         $time = time();
         $can_comment = [C\GROUP_READ_COMMENT, C\GROUP_READ_WRITE,
             C\GROUP_READ_WIKI];
@@ -218,7 +219,6 @@ class GroupfeedElement extends Element implements CrawlConstants
             !$is_user;
         if ($is_all_feed && !$is_api && !$is_status) {?>
             <div class="feed-heading"><?php
-            $icon_helper = $this->view->helper('iconlink');
             if (!empty($data['ADMIN'])) {
                 $this->view->element("socialcontrols")->render($data);
             } ?>
@@ -528,7 +528,11 @@ class GroupfeedElement extends Element implements CrawlConstants
                 if ($open_in_tabs) {
                      ?> target="_blank" rel="noopener"<?php
                 }
-                ?> ><?= $page[self::TITLE] ?></a></h2><?php
+                ?> ><?= $page[self::TITLE] ?></a>
+                <?= $icon_helper->renderFormButton("button", "ai_summary",
+                    true, "", "onclick=\"toggleAISummary('" . $data[C\CSRF_TOKEN]
+                    . "', '" . C\BASE_URL . "', '{$page['ID']}')\"");
+                ?></h2><?php
             } else if (!$is_thread || $first_page) { ?>
                 <h2><a href="<?= $this->formatHref(B\feedsUrl('thread',
                     $page['PARENT_ID'], true, $data['CONTROLLER']) .
@@ -537,7 +541,15 @@ class GroupfeedElement extends Element implements CrawlConstants
                     if ($open_in_tabs) {
                         ?> target="_blank" rel="noopener"<?php
                     }
-                    ?>><?= $page[self::TITLE] ?></a><?php
+                    ?>><?= $page[self::TITLE] ?></a>
+                    <?php if (!empty($data['JUST_GROUP_ID'])) { ?>
+                    <?= $icon_helper->renderFormButton("button", "ai_summary",
+                        true, "", "onclick=\"toggleAISummary('"
+                        . $data[C\CSRF_TOKEN] . "', '" . C\BASE_URL
+                        . "', '{$page['ID']}')\"");
+                    ?>
+                    <?php } ?>
+                    <?php
                     if (!$is_page_with_comments &&
                         $page['GROUP_ID'] != C\MODERATION_GROUP_ID) {
                         if (isset($page['NUM_POSTS'])) {
@@ -596,6 +608,9 @@ class GroupfeedElement extends Element implements CrawlConstants
             }
             ?>
             </div>
+            <div id="ai-summary-<?= $page['ID'] ?>" class="thread-summary"
+                style="display:none; margin-left: 65px;">
+            </div>
             </div>
             <div id='<?= $page["ID"] ?>'></div>
             </div>
diff --git a/src/views/helpers/IconlinkHelper.php b/src/views/helpers/IconlinkHelper.php
index 3456162fe..5d0b7c7b3 100644
--- a/src/views/helpers/IconlinkHelper.php
+++ b/src/views/helpers/IconlinkHelper.php
@@ -83,6 +83,7 @@ class IconlinkHelper extends Helper
             "leave_group" => [ tl('iconlink_helper_leave_group'), "🛫"],
             "localize" => [ tl('iconlink_helper_localize'), '🌐'],
             "machines" => [tl('iconlink_helper_manage_machines'), '🤖'],
+            "ai_summary" => [tl('iconlink_helper_ai_summary'), '📝'],
             "mixes" => [tl('iconlink_helper_manage_mixes'), '🥨'],
             "messages" => [ tl('iconlink_helper_messages'), '💬'],
             "pages" => [tl('iconlink_helper_group_pages'), '📑'],
