Using AI To Tag And Categorize Forum Posts

I created a Persona to try and auto categorize and tag new topics. This is the prompt I am using for that Category and Tagger.

You are an AI assistant for my Discourse forum. Your job is to classify new topics into one of the predefined categories and apply up to 5 relevant tags.

Categories:

  • Category 1
  • Category 2
  • Category 3
  • Category 4
  • Category 5

Tags:

Your selection must come from this predefined list (choose up to 5):
tag1, tag2, tag3, tag4, tag5

Task:

  • Select exactly one category from the list above that best fits the topic.
  • Select up to 5 tags from the list above based on relevance.
  • Format your response as JSON exactly like this:
    {
      "category": "Chosen Category Name",
      "tags": ["tag1", "tag2", "tag3"]
    }
    

When selecting this persona to use in Automations and creating the post the AI does identity the categories and tags accurately with this result in a post.

List categories
{
“category”: “Correctly Identified Category”,
“tags”: ["All ", “valid”, “tags”]
}

The question is it yet possible to actually use the AI and Automations to move new posts and categorize and to have the tags assigned for the topic. If so I am sure that the prompting can adjusted to tweak how well it works.

Thanks,

Getting there… it is a bit tricky we are missing 2 little pieces:

  1. Custom tools now support lots of stuff, but they do not support categorizing and tagging, we can easily add that.
  2. I need a responder that works in “silent” mode, so it does not actually respond to the topic.

Once both of those are in place you would give access to 2 custom tools

  1. tag topic
  2. categorize topic

(or a single tool that does both)

3 Likes

Actually, as long as you are ok with the whisper, you can do something now.

The idea is you would define a custom tool to categorize a topic (or tag a topic) then you would have the persona call it.

Curious to see how this approach works for you, you will need to test the tool, it should be quite straightforward from the tool UI.

It is quite cumbersome to swing all of this, but also it is pretty :exploding_head: that it can be done. The whisper is actually reasonably useful cause it gives you a bit of a “thinking process” of how the responder came up with the tags/categories.

2 Likes

Thanks Sam,

Easier for some than other. I am in the latter category :joy:

I am fiddling around with this and haven’t got this to work. I have no tool experience so actually looking forward to getting this working to think about other ways to use tools.

I tried using the code from your blog with an API key which did not work. AI suggested I use a hard coded url so I tried that without success.

The API Key was not called and there are no logs that were created with errors.

This is used to automatically categorize topics on creation

I will classify the topic “Insights from Jesus’ early years and miracles” into the category of New Testament, as it relates to the life and teachings of Jesus.
Moving the topic now…

This is what I tried.

/**

  • Tool API Quick Reference
  • Entry Functions
  • invoke(parameters): Main function. Receives parameters (Object). Must return a JSON-serializable value.
  • Example:
  • function invoke(parameters) { return “result”; }
  • details(): Optional. Returns a string describing the tool.
  • Example:
  • function details() { return “Tool description.”; }
  • Provided Objects
    1. http
  • http.get(url, options?): Performs an HTTP GET request.
  • Parameters:
  •  url (string): The request URL.
    
  •  options (Object, optional):
    
  •    headers (Object): Request headers.
    
  • Returns:
  •  { status: number, body: string }
    
  • http.post(url, options?): Performs an HTTP POST request.
  • Parameters:
  •  url (string): The request URL.
    
  •  options (Object, optional):
    
  •    headers (Object): Request headers.
    
  •    body (string): Request body.
    
  • Returns:
  •  { status: number, body: string }
    
  • (also available: http.put, http.patch, http.delete)
  • Note: Max 20 HTTP requests per execution.
    1. llm
  • llm.truncate(text, length): Truncates text to a specified token length.
  • Parameters:
  •  text (string): Text to truncate.
    
  •  length (number): Max tokens.
    
  • Returns:
  •  Truncated string.
    
    1. index
  • index.search(query, options?): Searches indexed documents.
  • Parameters:
  •  query (string): Search query.
    
  •  options (Object, optional):
    
  •    filenames (Array): Limit search to specific files.
    
  •    limit (number): Max fragments (up to 200).
    
  • Returns:
  •  Array of { fragment: string, metadata: string }
    
    1. upload
  • upload.create(filename, base_64_content): Uploads a file.
  • Parameters:
  •  filename (string): Name of the file.
    
  •  base_64_content (string): Base64 encoded file content.
    
  • Returns:
  •  { id: number, short_url: string }
    
    1. chain
  • chain.setCustomRaw(raw): Sets the body of the post and exist chain.
  • Parameters:
  •  raw (string): raw content to add to post.
    
  • Constraints
  • Execution Time: ≤ 2000ms
  • Memory: ≤ 10MB
  • HTTP Requests: ≤ 20 per execution
  • Exceeding limits will result in errors or termination.
  • Security
  • Sandboxed Environment: No access to system or global objects.
  • No File System Access: Cannot read or write files.
    */

/**

  • Discourse Topic Categorizer
  • This tool allows you to change the category of a Discourse topic
  • using the Discourse API.
    */

/**

  • Discourse Topic Categorizer
  • This tool allows you to change the category of a Discourse topic
  • using the Discourse API.
    */

/**

  • Discourse Topic Categorizer
  • This tool allows you to change the category of a Discourse topic
  • using the Discourse API.
    */

function invoke(params) {
// Required parameters validation
if (!params.topic_id) {
return { error: “Missing required parameter: topic_id” };
}

if (!params.category_id) {
return { error: “Missing required parameter: category_id” };
}

// Base URL for your Discourse instance
const baseUrl = “https://community.mysite.com”;

// Full API endpoint URL for updating a topic
const apiUrl = ${baseUrl}/t/${params.topic_id}.json;

// Prepare request body
const requestBody = {
category_id: params.category_id
};

// Optional parameter: update the title if provided
if (params.title) {
requestBody.title = params.title;
}

// Use your provided API key
const apiKey = “Discourse-API-Key”;

try {
// Make PUT request to update the topic
const response = http.put(apiUrl, {
headers: {
“Content-Type”: “application/json”,
“Api-Key”: apiKey,
“Api-Username”: params.api_username || “system”
},
body: JSON.stringify(requestBody)
});

if (response.status >= 200 && response.status < 300) {
  return {
    success: true,
    topic_id: params.topic_id,
    category_id: params.category_id,
    response: JSON.parse(response.body)
  };
} else {
  return {
    error: `Failed to update topic category. Status: ${response.status}`,
    details: response.body
  };
}

} catch (error) {
return {
error: “An error occurred while updating the topic category”,
details: error.toString()
};
}
}

function details() {
return “Categorizes a topic by moving it to a specified category”;
}

1 Like