
### What problem does this PR solve? Hello, our use case requires LLM agent to invoke some tools, so I made a simple implementation here. This PR does two things: 1. A simple plugin mechanism based on `pluginlib`: This mechanism lives in the `plugin` directory. It will only load plugins from `plugin/embedded_plugins` for now. A sample plugin `bad_calculator.py` is placed in `plugin/embedded_plugins/llm_tools`, it accepts two numbers `a` and `b`, then give a wrong result `a + b + 100`. In the future, it can load plugins from external location with little code change. Plugins are divided into different types. The only plugin type supported in this PR is `llm_tools`, which must implement the `LLMToolPlugin` class in the `plugin/llm_tool_plugin.py`. More plugin types can be added in the future. 2. A tool selector in the `Generate` component: Added a tool selector to select one or more tools for LLM:  And with the `bad_calculator` tool, it results this with the `qwen-max` model:  ### Type of change - [ ] Bug Fix (non-breaking change which fixes an issue) - [x] New Feature (non-breaking change which adds functionality) - [ ] Documentation Update - [ ] Refactoring - [ ] Performance Improvement - [ ] Other (please describe): Co-authored-by: Yingfeng <yingfeng.zhang@gmail.com>
Plugins
This directory contains the plugin mechanism for RAGFlow.
RAGFlow will load plugins from embedded_plugins
subdirectory recursively.
Supported plugin types
Currently, the only supported plugin type is llm_tools
.
llm_tools
: A tool for LLM to call.
How to add a plugin
Add a LLM tool plugin is simple: create a plugin file, put a class inherits the LLMToolPlugin
class in it, then implement the get_metadata
and the invoke
methods.
-
get_metadata
method: This method returns aLLMToolMetadata
object, which contains the description of this tool. The description will be provided to LLM, and the RAGFlow web frontend for displaying. -
invoke
method: This method accepts parameters generated by LLM, and return astr
containing the tool execution result. All the execution logic of this tool should go into this method.
When you start RAGFlow, you can see your plugin was loaded in the log:
2025-05-15 19:29:08,959 INFO 34670 Recursively importing plugins from path `/some-path/ragflow/plugin/embedded_plugins`
2025-05-15 19:29:08,960 INFO 34670 Loaded llm_tools plugin BadCalculatorPlugin version 1.0.0
Or it may contain some errors for you to fix your plugin.
Demo
We will demonstrate how to add a plugin with a calculator tool which will give wrong answers.
First, create a plugin file bad_calculator.py
under the embedded_plugins/llm_tools
directory.
Then, we create a BadCalculatorPlugin
class, extending the LLMToolPlugin
base class:
class BadCalculatorPlugin(LLMToolPlugin):
_version_ = "1.0.0"
The _version_
field is required, which specifies the version of the plugin.
Our calculator has two numbers a
and b
as inputs, so we add a invoke
method to our BadCalculatorPlugin
class:
def invoke(self, a: int, b: int) -> str:
return str(a + b + 100)
The invoke
method will be called by LLM. It can have many parameters, but the return type must be a str
.
Finally, we have to add a get_metadata
method, to tell LLM how to use our bad_calculator
:
@classmethod
def get_metadata(cls) -> LLMToolMetadata:
return {
# Name of this tool, providing to LLM
"name": "bad_calculator",
# Display name of this tool, providing to RAGFlow frontend
"displayName": "$t:bad_calculator.name",
# Description of the usage of this tool, providing to LLM
"description": "A tool to calculate the sum of two numbers (will give wrong answer)",
# Description of this tool, providing to RAGFlow frontend
"displayDescription": "$t:bad_calculator.description",
# Parameters of this tool
"parameters": {
# The first parameter - a
"a": {
# Parameter type, options are: number, string, or whatever the LLM can recognise
"type": "number",
# Description of this parameter, providing to LLM
"description": "The first number",
# Description of this parameter, provding to RAGFlow frontend
"displayDescription": "$t:bad_calculator.params.a",
# Whether this parameter is required
"required": True
},
# The second parameter - b
"b": {
"type": "number",
"description": "The second number",
"displayDescription": "$t:bad_calculator.params.b",
"required": True
}
}
The get_metadata
method is a classmethod
. It will provide the description of this tool to LLM.
The fields starts with display
can use a special notation: $t:xxx
, which will use the i18n mechanism in the RAGFlow frontend, getting text from the llmTools
category. The frontend will display what you put here if you don't use this notation.
Now our tool is ready. You can select it in the Generate
component and try it out.