Skip to content

Commit

Permalink
feat: 函数调用
Browse files Browse the repository at this point in the history
  • Loading branch information
sangyuxiaowu committed Jul 25, 2024
1 parent 47a7509 commit 82732e7
Show file tree
Hide file tree
Showing 8 changed files with 422 additions and 9 deletions.
6 changes: 5 additions & 1 deletion LLamaWorker.OpenAIModels/ChatCompletionModels.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
namespace LLamaWorker.OpenAIModels
using System.Text.Json.Serialization;

namespace LLamaWorker.OpenAIModels
{
/// <summary>
/// 对话完成请求
Expand Down Expand Up @@ -54,13 +56,15 @@ public class ChatCompletionMessage
/// 工具调用信息
/// </summary>
/// <example>null</example>
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
public ToolMeaasge[]? tool_calls { get; set; }

/// <summary>
/// 调用工具的 ID
/// role 为 tool 时必填
/// </summary>
/// <example>null</example>
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
public string? tool_call_id { get; set; }
}

Expand Down
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ English | [中文](README_CN.md)
- **Embedding Support**: Provides text embedding functionality with support for various embedding models.
- **chat templates**: Provides some common chat templates.
- **Auto-Release**: Supports automatic release of loaded models.
- **Function Call**: Supports function calls.
- **API Key Authentication**: Supports API Key authentication.
- **Gradio UI Demo**: Provides a UI demo based on Gradio.NET.

Expand Down
1 change: 1 addition & 0 deletions README_CN.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ LLamaWorker 是一个基于 [LLamaSharp](https://github.com/SciSharp/LLamaSharp?
- **嵌入支持**: 提供文本嵌入功能,支持多种嵌入模型。
- **对话模版**: 提供了一些常见的对话模版。
- **自动释放**: 支持自动释放已加载模型。
- **函数调用**: 支持函数调用。
- **API Key 认证**: 支持 API Key 认证。
- **Gradio UI Demo**: 提供了一个基于 Gradio.NET 的 UI 演示。

Expand Down
33 changes: 33 additions & 0 deletions src/FunctionCall/ToolPromptGenerator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,39 @@ public ToolPromptConfig GetToolPromptConfig(int tpl = 0)
return _config[tpl];
}

/// <summary>
/// 生成工具调用
/// </summary>
/// <param name="tool">工具调用消息</param>
/// <param name="tpl">模版序号</param>
/// <returns></returns>
public string GenerateToolCall(ToolMeaasge tool, int tpl = 0)
{
return $"{_config[tpl].FN_NAME}: {tool.function.name}\n{_config[tpl].FN_ARGS}: {tool.function.arguments}";
}

/// <summary>
/// 生成工具返回结果
/// </summary>
/// <param name="res">工具调用结果</param>
/// <param name="tpl">模版序号</param>
/// <returns></returns>
public string GenerateToolCallResult(string? res, int tpl = 0)
{
return $"{_config[tpl].FN_RESULT}: {res}";
}

/// <summary>
/// 生成工具推理结果
/// </summary>
/// <param name="res">工具推理结果</param>
/// <param name="tpl">模版序号</param>
/// <returns></returns>
public string GenerateToolCallReturn(string? res, int tpl = 0)
{
return $"{_config[tpl].FN_EXIT}: {res}";
}

/// <summary>
/// 检查并生成工具调用
/// </summary>
Expand Down
288 changes: 286 additions & 2 deletions src/LLamaWorker.http
Original file line number Diff line number Diff line change
Expand Up @@ -71,11 +71,295 @@ Content-Type: application/json
"messages": [
{
"role": "system",
"content": "You are a helpful assistant."
"content": "你是用户 SangYuXiaoWu 的助理,你会遵守规则。您将完成所需的步骤并在采取任何后续行动之前请求批准。\r\n如果用户不提供足够的信息让你完成一项任务,你会一直问问题,直到你有足够的信息来完成任务。"
},
{
"role": "user",
"content": "帮我给我的老板,老周写一封邮件说我要涨薪"
}
],
"tools": [
{
"function": {
"name": "AuthorEmailPlanner-GenerateRequiredSteps",
"description": "返回编写电子邮件所需的必要步骤。",
"parameters": {
"type": "object",
"required": [
"topic",
"recipients"
],
"properties": {
"topic": {
"type": "string",
"description": "电子邮件内容的2-3句简要描述"
},
"recipients": {
"type": "string",
"description": "收件人的描述"
}
}
}
},
"type": "function"
},
{
"function": {
"name": "EmailPlugin-SendEmail",
"description": "向收件人发送电子邮件。",
"parameters": {
"type": "object",
"required": [
"recipientEmails",
"subject",
"body"
],
"properties": {
"recipientEmails": {
"type": "string",
"description": "以分号分隔的收件人电子邮件列表"
},
"subject": {
"type": "string"
},
"body": {
"type": "string"
}
}
}
},
"type": "function"
}
],
"tool_choice": "auto"
}

###
# 测试调用结果
POST {{LLamaWorker_HostAddress}}/v1/chat/completions
Content-Type: application/json

{
"model": "gpt-3.5-turbo",
"messages": [
{
"role": "system",
"content": "你是用户 SangYuXiaoWu 的助理,你会遵守规则。您将完成所需的步骤并在采取任何后续行动之前请求批准。\r\n如果用户不提供足够的信息让你完成一项任务,你会一直问问题,直到你有足够的信息来完成任务。"
},
{
"role": "user",
"content": "帮我给我的老板,老周写一封邮件说我要涨薪"
},
{
"role": "assistant",
"content": null,
"tool_calls": [
{
"id": "call_7dd44be53d3048a9ba9735c7be0133f6",
"type": "function",
"function": {
"name": "AuthorEmailPlanner-GenerateRequiredSteps",
"arguments": "{\"topic\": \"请求增加薪资\", \"recipients\": \"\"}"
}
}
]
},
{
"role": "tool",
"content": "当然,以下是建议的前三个步骤来准备你的加薪请求电子邮件:\n\n1. **研究和准备**:\n - **市场调研**:了解行业标准和同类职位的薪酬水平,以便有理有据地提出加薪请求。\n - **个人贡献总结**:列出你在公司期间的成就、项目经验以及对团队和公司的贡献。\n - **公司业绩了解**:了解公司目前的财务状况和业绩,确保选择一个合适的时机。\n\n2. **明确你的请求**:\n - **具体数字**:决定你希望加薪的具体金额或百分比。\n - **理由清晰**:准备好阐述加薪的合理性,包括你的研究结果和个人贡献。\n\n3. **起草邮件**:\n - **语气专业**:确保邮件语气正式、礼貌,同时表达出你的感激之情和对公司的热爱。\n - **结构清晰**:确保邮件结构清晰,有明确的开头(表明请求)、正文(提出理由)和结尾(感谢和期待回复)。\n\n这样,你既能确保邮件专业性,也能增强请求的说服力。",
"tool_call_id": "call_7dd44be53d3048a9ba9735c7be0133f6"
}
],
"tools": [
{
"function": {
"name": "AuthorEmailPlanner-GenerateRequiredSteps",
"description": "返回编写电子邮件所需的必要步骤。",
"parameters": {
"type": "object",
"required": [
"topic",
"recipients"
],
"properties": {
"topic": {
"type": "string",
"description": "电子邮件内容的2-3句简要描述"
},
"recipients": {
"type": "string",
"description": "收件人的描述"
}
}
}
},
"type": "function"
},
{
"function": {
"name": "EmailPlugin-SendEmail",
"description": "向收件人发送电子邮件。",
"parameters": {
"type": "object",
"required": [
"recipientEmails",
"subject",
"body"
],
"properties": {
"recipientEmails": {
"type": "string",
"description": "以分号分隔的收件人电子邮件列表"
},
"subject": {
"type": "string"
},
"body": {
"type": "string"
}
}
}
},
"type": "function"
}
],
"tool_choice": "auto"
}

###
# 测试调用结果
POST {{LLamaWorker_HostAddress}}/v1/chat/completions
Content-Type: application/json

{
"model": "gpt-3.5-turbo",
"messages": [
{
"role": "system",
"content": "你是用户 SangYuXiaoWu 的助理,你会遵守规则。您将完成所需的步骤并在采取任何后续行动之前请求批准。\r\n如果用户不提供足够的信息让你完成一项任务,你会一直问问题,直到你有足够的信息来完成任务。"
},
{
"role": "user",
"content": "帮我给我的老板,老周写一封邮件说我要涨薪"
},
{
"role": "assistant",
"content": null,
"tool_calls": [
{
"id": "call_7dd44be53d3048a9ba9735c7be0133f6",
"type": "function",
"function": {
"name": "AuthorEmailPlanner-GenerateRequiredSteps",
"arguments": "{\"topic\": \"请求增加薪资\", \"recipients\": \"\"}"
}
}
]
},
{
"role": "tool",
"content": "当然,以下是建议的前三个步骤来准备你的加薪请求电子邮件:\n\n1. **研究和准备**:\n - **市场调研**:了解行业标准和同类职位的薪酬水平,以便有理有据地提出加薪请求。\n - **个人贡献总结**:列出你在公司期间的成就、项目经验以及对团队和公司的贡献。\n - **公司业绩了解**:了解公司目前的财务状况和业绩,确保选择一个合适的时机。\n\n2. **明确你的请求**:\n - **具体数字**:决定你希望加薪的具体金额或百分比。\n - **理由清晰**:准备好阐述加薪的合理性,包括你的研究结果和个人贡献。\n\n3. **起草邮件**:\n - **语气专业**:确保邮件语气正式、礼貌,同时表达出你的感激之情和对公司的热爱。\n - **结构清晰**:确保邮件结构清晰,有明确的开头(表明请求)、正文(提出理由)和结尾(感谢和期待回复)。\n\n这样,你既能确保邮件专业性,也能增强请求的说服力。",
"tool_call_id": "call_7dd44be53d3048a9ba9735c7be0133f6"
}
],
"tools": [
{
"function": {
"name": "AuthorEmailPlanner-GenerateRequiredSteps",
"description": "返回编写电子邮件所需的必要步骤。",
"parameters": {
"type": "object",
"required": [
"topic",
"recipients"
],
"properties": {
"topic": {
"type": "string",
"description": "电子邮件内容的2-3句简要描述"
},
"recipients": {
"type": "string",
"description": "收件人的描述"
}
}
}
},
"type": "function"
},
{
"function": {
"name": "EmailPlugin-SendEmail",
"description": "向收件人发送电子邮件。",
"parameters": {
"type": "object",
"required": [
"recipientEmails",
"subject",
"body"
],
"properties": {
"recipientEmails": {
"type": "string",
"description": "以分号分隔的收件人电子邮件列表"
},
"subject": {
"type": "string"
},
"body": {
"type": "string"
}
}
}
},
"type": "function"
}
],
"tool_choice": "auto"
}

###
# 测试确认发送
POST {{LLamaWorker_HostAddress}}/v1/chat/completions
Content-Type: application/json

{
"model": "gpt-3.5-turbo",
"messages": [
{
"role": "system",
"content": "你是用户 SangYuXiaoWu 的助理,你会遵守规则。您将完成所需的步骤并在采取任何后续行动之前请求批准。\r\n如果用户不提供足够的信息让你完成一项任务,你会一直问问题,直到你有足够的信息来完成任务。"
},
{
"role": "user",
"content": "帮我给我的老板,老周写一封邮件说我要涨薪"
},
{
"role": "assistant",
"content": null,
"tool_calls": [
{
"id": "call_7dd44be53d3048a9ba9735c7be0133f6",
"type": "function",
"function": {
"name": "AuthorEmailPlanner-GenerateRequiredSteps",
"arguments": "{\"topic\": \"请求增加薪资\", \"recipients\": \"\"}"
}
}
]
},
{
"role": "tool",
"content": "当然,以下是建议的前三个步骤来准备你的加薪请求电子邮件:\n\n1. **研究和准备**:\n - **市场调研**:了解行业标准和同类职位的薪酬水平,以便有理有据地提出加薪请求。\n - **个人贡献总结**:列出你在公司期间的成就、项目经验以及对团队和公司的贡献。\n - **公司业绩了解**:了解公司目前的财务状况和业绩,确保选择一个合适的时机。\n\n2. **明确你的请求**:\n - **具体数字**:决定你希望加薪的具体金额或百分比。\n - **理由清晰**:准备好阐述加薪的合理性,包括你的研究结果和个人贡献。\n\n3. **起草邮件**:\n - **语气专业**:确保邮件语气正式、礼貌,同时表达出你的感激之情和对公司的热爱。\n - **结构清晰**:确保邮件结构清晰,有明确的开头(表明请求)、正文(提出理由)和结尾(感谢和期待回复)。\n\n这样,你既能确保邮件专业性,也能增强请求的说服力。",
"tool_call_id": "call_7dd44be53d3048a9ba9735c7be0133f6"
},
{
"role": "assistant",
"content": "现在我已经准备好了写邮件的步骤。以下是建议的邮件内容概述:\n\n---\n\n**主题:关于薪资调整的请求**\n\n尊敬的老周,\n\n在我于[公司名]的这段宝贵时间里,我深知能够实践我的技能和兴趣,为公司带来了独特的价值,并且我和团队一起取得了许多成功的项目与成就。这些成长都归功于此工作环境提供了无比的支持、资源和机会。\n\n通过市场调研及我在职位上的表现,我认为我的贡献已提升到一个新层次。根据当前行业标准以及个人贡献的情况,我期望将薪资调整为[具体薪资数字]元/月(或百分比上升至[具体百分比]%),这反映了我的专业技能的提高及对公司成长做出的重大贡献。\n\n此请求不仅仅基于我的职业规划和发展考虑,同时也出于公司利益考量。为公平起见,并保持我们作为行业领导者的工作氛围,我希望这次调薪能够正式化,使我得到相应的认可和回报。\n\n因此,我恳请您认真考虑这提议,并安排一个时间进行深入的讨论,以便我们可以更详细地交流这个话题及其实施的可能性。\n\n感谢您一直以来的支持与指导。我期待着与您进一步探讨此事,并相信我们能够共同找到一套满意且对双方都充满正面影响的解决方案。\n\n顺祝商祺,\n\n[您的名字]\n---\n\n请检查和修改这段文本以适应你的具体情况,确保所有细节都是准确且合适的。完成后,你可以使用EmailPlugin-SendEmail工具将邮件发送出去。"
},
{
"role": "user",
"content": "Email to John Smith with the subject 'Meeting' and the body 'Hi John, I wanted to follow up on our meeting from last week. When are you available to meet again?'"
"content": "大体框架没有问题,可以发送"
}
],
"tools": [
Expand Down
4 changes: 2 additions & 2 deletions src/Services/LLmModelService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -339,13 +339,13 @@ private ChatHistoryResult GetChatHistory(ChatCompletionRequest request)
var historyTransform = Activator.CreateInstance(type) as ITemplateTransform;
if (historyTransform != null)
{
history = historyTransform.HistoryToText(messages, toolPrompt);
history = historyTransform.HistoryToText(messages, _toolPromptGenerator, toolPrompt);
}
}
}
else
{
history = new BaseHistoryTransform().HistoryToText(messages, toolPrompt);
history = new BaseHistoryTransform().HistoryToText(messages, _toolPromptGenerator, toolPrompt);
}

return new ChatHistoryResult(history, toolenabled, toolstopwords);
Expand Down
Loading

0 comments on commit 82732e7

Please sign in to comment.