文章阅读目录大纲
https://github.com/rsharp-lang/athena
在这博客篇文章中的Idea来自于最近进行AI Agent的开发:希望可以有一个方便的框架,能够让我像写普通的R#程序包的方式,为大语言模型编写对应的工具包,实现AI Agent功能。经过了大概一天的摸索,搞定了这样子的AI Agent的框架。我将这个框架取名为雅典娜系统。关于这个系统的名称,我们首先来看看DeepSeek是怎么说的:
“我现在正在开发一个和大语言模型助手相关的工具,这个工具可以完成通过自然语言聊天的方式调用相应的工具完成生信数据分析,我需要为这个项目取一个名称,要求这个项目的名称应该是符合下面的需求的:女孩英文名称,和智慧相关的,和科学相关的。为我列举一些候选名称”
根据你的需求(女孩英文名、智慧与科学相关),结合搜索结果中的历史文化名人和寓意,以下是推荐的候选名称及来源解析:
名字 寓意 关联 Athena 源自希腊神话的智慧女神,象征智慧与科学战略。 雅典娜不仅是智慧化身,也代表理性思维,适合强调数据分析与策略的项目。 Clara 拉丁语“明亮、清晰”,象征清晰的科学思维。 历史上克拉拉·舒曼(音乐家)虽非科学家,但名字的“明亮”特质契合数据分析的精准性。 Rosalind 取自科学家罗莎琳德·富兰克林(Rosalind Franklin),DNA结构发现者。 直接映射生物学与数据解析,适合基因数据分析类工具。 推荐组合示例:
- Athena.AI(突出智慧与科技感)
- ClaraLabs(强调清晰的数据洞察)
- Rosalind.Analytics(关联生物信息学)
“这个框架系统我打算取名为 Athena AI System , 在保留Athena 这个名字的基础上,可以帮助我想出一些更好的名字候选给我么”
基于Athena AI的技术特性和命名最佳实践,我为您设计了以下候选名称方案,既保留品牌核心标识,又强化技术定位与市场差异化:
技术驱动型命名(突出架构创新)
Athena NeuroCore System
命名逻辑:强调神经网络核心架构,呼应其多模型融合能力
Neuro体现认知智能,Core突出框架的基础性作用。
Athena QuantumInsight Platform
技术关联:结合量子计算隐喻,暗示处理庞大数据时的指数级效率提升,与One-Bit技术带来的20倍效率突破形成联想。
Athena Decentralized Intelligence Hub
核心价值:突出去中心化特性与区块链集成能力,契合其社区驱动模式与Substrate层技术架构。
按照大语言模型的推荐的第一位,我们针对这个LLMs开发框架取名为:Athena NeuroCore System。下面我们就来具体的了解这样的一个开发框架的具体实现细节。
在进行本文的阅读之前,推荐可以往回阅读本工作的基础工具的开发记录。系列文章回顾:
定义一个工具
雅典娜框架是一种与MCP服务类似的LLMs工具标准化的定义工具。只不过MCP服务更加注重网络环境的分享,而雅典娜框架则是更加注重本地环境上的AI工具的集成。在不借助于任何框架的帮助的情况下,我们进行AI工具的定义一般会需要专门自己编写相应的工具描述信息json,函数调用过程,然后添加到大语言模型环境中。而基于雅典娜框架进行AI工具的开发,则可以能够让我们更加的专注于工具函数内部的我们需要实现的业务逻辑实现的开发工作,无需过多的关注与LLMs的交互和集成的问题。
关于如何在R#中,基于雅典娜框架定义一个AI工具,我们可以直接按照正常的R#函数代码的编写来实现即可,无需额外的过多的学习成本。例如,一般的,我们在我们的脚本中写下下面的一个函数用于支持帮助大语言模型在聊天界面上显示出一张图片:
#' creaate image url
#'
#' @details convert the local image file path as the url could be used as the src attribute value of
#' the html img tag. images format supports svg/png/bmp/jpg/jpeg/webp/gif.
#'
#' @param img_file the target image file path ffor make convert to http url
#'
[@ollama "image_url"]
const image_url = function(img_file) {
list(
img = {
src: file_proxy(img_file),
filename: basename(img_file, withExtensionName = TRUE)
}
)
}
通过上面的一个简单的函数示例,我们是否可以很惊奇的发现,使用R#语言开发一个可以被LLMs调用的AI Agent工具这也太简单了吧。就是写具体的工具函数就可以了,除了我们需要在我们的函数上额外的添加一个名字为
的自定义属性,不需要在其他的任何地方上做与LLMs有关的修改。一般的,通过雅典娜框架进行AI Agent工具的开发,可以通过下面的映射关系很方便的创建出一个可以被LLMs调用的工具函数:ollama
R#元素 | LLMs消息定义 | 说明 |
---|---|---|
自定义属性 |
工具名 | 主要是基于在R#中进行反射操作,基于扫描函数是否具有ollama这个标签来获取运行时环境中的工具函数关联 |
函数描述 |
工具描述信息 | R#会解析函数的Roxygon注释文档,通过使用注释文档的描述内容作为LLMs工具的描述信息 |
参数描述 |
工具参数信息 | R#会解析函数的Roxygon注释文档,通过使用注释文档的参数文档信息作为LLMs工具的参数描述信息 |
通过雅典娜框架的解析工作,我们就可以自动的从上面的函数定义信息解析出来可以传递给LLMs的工具信息,相应的生成的json内容如下所示:
{
type: "function",
function: {
name: "image_url",
description: "convert the local image file path as the url could be used as the src attribute value of the html img tag. images format supports svg/png/bmp/jpg/jpeg/webp/gif.",
parameters: {
type: "object",
required: ["img_file"],
properties: {
img_file: {
name: "img_file",
type: "string",
description: "the target image file path ffor make convert to http url"
}
}
}
}
}
那我们是如何实现上面的转换过程的呢?下面我们就来看看具体的
语言的反射代码的实现过程:R#
# scan R# runtime and load function call tools
# into the ollama client
for(let func in ollama_tools) {
# [@ollama "tool_name"]
let attrs = .Internal::attributes(func);
let tool_name = attrs$ollama;
let roxygon = as.list(.Internal::docs(func));
let desc_str = which([roxygon$description, roxygon$details], s -> nchar(s) > 0);
let args = lapply(roxygon$parameters, t -> t$text, names = t -> t$name);
let requires = which(roxygon$declares$parameters, p -> is.null(p$text)) |> sapply(p -> p$name);
cat(`[ollama]attach_tool: ${tool_name}\n`);
ollama::add_tool(deepseek,
name = tool_name,
desc = paste(desc_str, sepc = " "),
requires = requires,
args = args) <- func;
}
从上面的代码中,有几个比较重要的工具函数应用在这个过程中:
反射函数 | 功能 | LLMs工具映射 |
---|---|---|
attributes | 通过反射操作获取函数上所定义的自定义属性列表 | 用于获取ollama标签,工具名称 |
docs | 通过反射操作获取函数上所定义的Roxygon编译出来的注释文档对象 | 用于获取工具的描述信息 |
ollama::add_tool | 向ollama客户端注册一个新的可以被LLMs发现的工具函数 | 用于添加函数工具信息到LLMs消息之中 |
总结,我们只需要关注于AI工具函数本身的内部的业务逻辑的实现和编写,无需额外的关注与LLMs的集成问题。这些问题在本框架中会通过一个标准化的方式自动扫描出我们所标记的工具,然后自动化的添加入大语言模型运行环境之中,供大语言模型来进行调用。
添加一个工具
在上面的代码中,雅典娜框架所扫描出来的运行时环境之中的AI工具都需要通过
这个函数来向LLMs消息之中添加工具函数的定义描述信息。add_tool这个函数是封装在VB.NET库中的一个Api函数,这个Api函数来自于LLMs程序包。这个函数的主要功能就是将从R#脚本中接收到的工具描述信息构建出大语言模型所需要的工具描述信息结构化文本对象,以及将对应的工具函数注册到大语言模型的工具客户端运行环境之中。其具体的实现代码如下所示:ollama::add_tool
<ExportAPI("add_tool")>
Public Function add_tool(model As Ollama.Ollama, name$, desc$,
<RRawVectorArgument>
requires As Object,
Optional args As list = Nothing,
<RByRefValueAssign>
Optional fcall As RFunction = Nothing,
Optional env As Environment = Nothing) As Object
Dim argList As New Dictionary(Of String, ParameterProperties)
If fcall Is Nothing Then
Return RInternal.debug.stop("Missing function value for make LLMs tool call!", env)
End If
If Not args Is Nothing Then
For Each arg As String In args.getNames
Call argList.Add(arg, New ParameterProperties With {
.name = arg,
.description = CLRVector.asCharacter(args.getByName(arg)).JoinBy(vbCrLf)
})
Next
End If
Dim f As New FunctionModel With {
.name = name,
.description = desc,
.parameters = New FunctionParameters With {
.required = CLRVector _
.asCharacter(requires) _
.SafeQuery _
.ToArray,
.properties = argList
}
}
Call model.AddFunction(
f, Function(arg)
Dim argSet As InvokeParameter() = arg.arguments _
.SafeQuery _
.Select(Function(a, i) New InvokeParameter(a.Key, a.Value, index:=i + 1)) _
.ToArray
Dim eval As Object = fcall.Invoke(env, argSet)
If TypeOf eval Is ReturnValue Then
eval = DirectCast(eval, ReturnValue).Evaluate(env)
End If
If TypeOf eval Is list Then
' to json
eval = env.globalEnvironment.doCall(
"JSON::json_encode",
New NamedValue(Of Object)("x", eval),
New NamedValue(Of Object)("env", env)
)
End If
If eval Is Nothing Then
Return "nothing returns"
ElseIf TypeOf eval Is Message Then
Return $"Error: {DirectCast(eval, Message).message.JoinBy("")}"
Else
Return CLRVector.asCharacter(eval).JoinBy("")
End If
End Function)
Return model
End Function
工具实现效果
我们通过前面的介绍可以知道,我们可以通过这个框架可以非常快速的开发出一个可以被大语言模型所调用的工具包。具体有多方便呢,就看看下面的运行代码吧:
# load your LLMs tools package before loading Athena system
require(Athena);
include(relative_work("../etc/app.json"));
# run app
run_http(
httpPort = getOption("listen"),
webContext = relative_work("../web/")
);
就只有短短的几行代码,你就可以基于雅典娜框架运行你的AI Agent工具代码:
- 首先第一个,加载你的AI Agent工具包到R#环境之中
- 接着通过
加载雅典娜框架到R#环境之中require(Athena);
- 通过
函数加载配置文件信息include
- 最后,通过
函数来启动你的AI应用run_http
雅典娜框架对应的配置文件内容也非常的简单:
{
"ollama_server": "127.0.0.1:11434",
"ollama_model": "qwen3:30b",
"listen": 80
}
我们只需要定义好Ollama服务信息,以及运行AI应用的http服务信息参数即可,其他的都不需要管了。现在来看看上面所举例的图片工具的使用效果怎么样:
工作得非常的完美!
与MCP服务的即插即用效果比较
相像一下,现在你需要往一台离线的服务器上面部署LLMs可以被调用的工具。由于MCP服务是依赖于网络服务的,所以这意味着在离线服务器上进行多种来源的MCP服务的工具部署,你需要依次部署安装并且启动多个MCP服务。通常这个时候需要安装多个服务实例。每个服务可能需要独立的配置和运行环境。
然而对于基于雅典娜框架的工具而言,其所有工具都是通过一种标准化的反射方式进行自动扫描生成。我们在一台离线服务器上部署基于雅典娜框架的AI工具,只需要在外部开发测试好对应的程序包,然后拷贝到离线服务器上,安装进R#语言的包环境之中,然后在代码中通过添加
函数来加载新安装的工具包即可。不需要做过多的环境修改,服务部署的工作。require
- 基于R#语言的LLMs大语言模型工具开发 - 2025年5月23日
- 为大语言模型运行添加工具调用 - 2025年5月23日
- 从头创建一个DeepSeek客户端 - 2025年5月18日
No responses yet