Compare commits

..

7 Commits

Author SHA1 Message Date
f710ed4b8e 🐛修复编码问题 2024-11-24 01:44:42 +08:00
39aa462483 🐛修复编码问题,fk windows 2024-11-24 01:36:17 +08:00
c1a3f19b23 修改.gitignore 2024-11-23 21:27:24 +08:00
aabd33f189 🛠️添加小棉工具功能,移除MARSHOAI_ENABLE_TIME_PROMPT配置项 2024-11-23 21:27:24 +08:00
Akarin~
3a764f5ea9 Create README_TOOLS.md 2024-11-23 21:14:32 +08:00
dd1191e602 新增混元生图功能(未完善) 2024-11-21 19:38:09 +08:00
ce6f51f9c9 新增允许添加更多支持图片模型的配置项 2024-11-21 01:21:50 +08:00
16 changed files with 382 additions and 23 deletions

1
.gitignore vendored
View File

@@ -167,3 +167,4 @@ cython_debug/
bot.py bot.py
pdm.lock pdm.lock
praises.json praises.json
*.bak

View File

@@ -100,6 +100,9 @@ _✨ 使用 OpenAI 标准格式 API 的聊天机器人插件 ✨_
当 nonebot 连接到支持的 OneBot v11 实现端时,可以接收头像双击戳一戳消息并进行响应。详见`MARSHOAI_POKE_SUFFIX`配置项。 当 nonebot 连接到支持的 OneBot v11 实现端时,可以接收头像双击戳一戳消息并进行响应。详见`MARSHOAI_POKE_SUFFIX`配置项。
## 🛠️ 小棉工具
小棉工具(MarshoTools)是`v0.5.0`版本的新增功能,支持加载外部函数库来为 Marsho 提供 Function Call 功能。[使用文档](./README_TOOLS.md)
## 👍 夸赞名单 ## 👍 夸赞名单
夸赞名单存储于插件数据目录下的`praises.json`里(该目录路径会在 Bot 启动时输出到日志),当配置项为`true` 夸赞名单存储于插件数据目录下的`praises.json`里(该目录路径会在 Bot 启动时输出到日志),当配置项为`true`
@@ -139,11 +142,12 @@ _✨ 使用 OpenAI 标准格式 API 的聊天机器人插件 ✨_
| MARSHOAI_ENABLE_SUPPORT_IMAGE_TIP | 否 | `true` | 启用后用户发送带图请求时若模型不支持图片,则提示用户 | | MARSHOAI_ENABLE_SUPPORT_IMAGE_TIP | 否 | `true` | 启用后用户发送带图请求时若模型不支持图片,则提示用户 |
| MARSHOAI_ENABLE_NICKNAME_TIP | 否 | `true` | 启用后用户未设置昵称时提示用户设置 | | MARSHOAI_ENABLE_NICKNAME_TIP | 否 | `true` | 启用后用户未设置昵称时提示用户设置 |
| MARSHOAI_ENABLE_PRAISES | 否 | `true` | 是否启用夸赞名单功能 | | MARSHOAI_ENABLE_PRAISES | 否 | `true` | 是否启用夸赞名单功能 |
| MARSHOAI_ENABLE_TIME_PROMPT | 否 | `true` | 是否启用实时更新的日期与时间(精确到秒)与农历日期系统提示词 | | MARSHOAI_ENABLE_TOOLS | 否 | `true` | 是否启用小棉工具(MarshoTools) |
| MARSHOAI_AZURE_ENDPOINT | 否 | `https://models.inference.ai.azure.com` | OpenAI 标准格式 API 端点 | | MARSHOAI_AZURE_ENDPOINT | 否 | `https://models.inference.ai.azure.com` | OpenAI 标准格式 API 端点 |
| MARSHOAI_TEMPERATURE | 否 | 无 | 进行推理时的温度参数 | | MARSHOAI_TEMPERATURE | 否 | 无 | 进行推理时的温度参数 |
| MARSHOAI_TOP_P | 否 | 无 | 进行推理时的核采样参数 | | MARSHOAI_TOP_P | 否 | 无 | 进行推理时的核采样参数 |
| MARSHOAI_MAX_TOKENS | 否 | 无 | 返回消息的最大 token 数 | | MARSHOAI_MAX_TOKENS | 否 | 无 | 返回消息的最大 token 数 |
| MARSHOAI_ADDITIONAL_IMAGE_MODELS | 否 | `[]` | 额外添加的支持图片的模型列表,例如`hunyuan-vision` |
## ❤ 鸣谢&版权说明 ## ❤ 鸣谢&版权说明

86
README_TOOLS.md Normal file
View File

@@ -0,0 +1,86 @@
# 🛠️小棉工具
小棉工具(MarshoTools)是一个简单的模块加载器,允许从插件数据目录下的`tools`目录内加载数个工具包与其中定义的函数,以供 AI 模型调用。
有关 Function Call 的更多信息,请参阅[OpenAI 官方文档](https://platform.openai.com/docs/guides/function-calling)。
## ✍️ 编写工具
### 📁 目录结构
插件数据目录下的`tools`目录被称作**工具集**,其中可包含数个**工具包**,工具包与 Python 的**包**结构类似,需要在其中包含`__init__.py`文件与`tools.json`定义文件,这些文件将被用于存放以及定义编写的函数。
一个工具包的目录结构类似于:
```
tools/ # 工具集目录
└── marshoai-example/ # 工具包目录,以包名命名
└── __init__.py # 工具模块
└── tools.json # 函数定义文件
```
在这个目录树中:
- **工具包目录**是以`marshoai-xxxxx`命名的目录,目录名即为工具包的包名。编写工具时,应尽量采取此命名标准。
- **工具模块**可包含数个可调用的**异步**函数,可以接受入参,也可以不接受。它们的返回值数据类型应为 AI 模型受支持的类型,一般情况下`str`被大部分模型所支持。
- **函数定义文件**是让 AI 模型知道如何调用这些函数的关键。
### 编写函数
来编写一个简单的函数吧,例如一个获取天气的函数和一个获取时间的函数:
###### **\_\_init\_\_.py**
```python
from datetime import datetime
async def get_weather(location: str):
return f"{location}的温度是114514℃。" #模拟天气返回信息
async def get_current_time():
current_time = datetime.now().strftime("%Y.%m.%d %H:%M:%S")
time_prompt = f"现在的时间是{current_time}"
return time_prompt
```
在这个示例代码中,定义了`get_weather``get_current_time`两个函数,其中一个接受`str`类型的地点入参。要让 AI 模型知道这两个函数的存在以及调用的条件和方法,需要编写**函数定义文件**。
###### **tools.json**
```json
[
{
"type": "function",
"function": {
"name": "marshoai-example__get_weather", #
"description": "查询指定地点的天气。", #
"parameters": { #
"type": "object",
"properties": {
"location": { # 'location'__init__.py
"type": "string", #
"description": "城市或县区,比如北京市、杭州市、余杭区等。" #
}
}
},
"required": [ #
"location"
]
}
},
{
"type": "function",
"function": {
"name": "marshoai-example__get_current_time",
"description": "获取现在的时间。",
"parameters": {} #
}
}
]
```
在这个文件中定义了两个已经编写好的函数,该定义文件将被输入到 AI 模型中,来让 AI 模型知道这些函数的存在与调用方法。
**函数调用名称**的命名方式比较特别。以获取天气的函数为例,它的函数调用名称`marshoai-example__get_weather`包含三个信息:
- 前面的**marshoai-example**即为该函数所在工具包的**包名**。
- 后面的**get_weather**是这个函数在代码里的名称。
- 中间的两个下划线是用于分割这两个信息的分隔符。
使用这种命名方式,是为了兼容更多的 OpenAI 标准格式 API。因此在给工具包和函数取名时不要使用带有两个下划线的名称。
### 测试函数
在编写完工具后,启动 BotNonebot 的日志应当会输出工具包的加载信息。
以下是测试示例:
```
> marsho 深圳天气怎么样
深圳的天气显示温度是114514°C真是不可思议呢这一定是个误报吧~(≧▽≦) 希望你那里有个好天气哦!
> marsho 分别告诉我下北泽,杭州,苏州的天气
下北泽、杭州和苏州的天气都显示温度为114514°C呢这么奇怪的温度一定是个误报吧~(≧▽≦)
如果要查看真实的天气情况,建议查看专业天气预报哦~
> marsho 现在几点了
现在的时间是2024年11月23日21点05分哦~(*^ω^) 你准备做些什么呢?
```

View File

@@ -1,8 +1,8 @@
from nonebot.plugin import require from nonebot.plugin import require
require("nonebot_plugin_alconna") require("nonebot_plugin_alconna")
require("nonebot_plugin_localstore") require("nonebot_plugin_localstore")
from .azure import * from .azure import *
#from .hunyuan import *
from nonebot import get_driver, logger from nonebot import get_driver, logger
from .config import config from .config import config
from .metadata import metadata from .metadata import metadata

View File

@@ -1,15 +1,18 @@
import contextlib import contextlib
import traceback import traceback
from typing import Optional from typing import Optional
from pathlib import Path
from arclet.alconna import Alconna, Args, AllParam from arclet.alconna import Alconna, Args, AllParam
from azure.ai.inference.models import ( from azure.ai.inference.models import (
UserMessage, UserMessage,
AssistantMessage, AssistantMessage,
ToolMessage,
TextContentItem, TextContentItem,
ImageContentItem, ImageContentItem,
ImageUrl, ImageUrl,
CompletionsFinishReason, CompletionsFinishReason,
ChatCompletionsToolCall,
) )
from azure.core.credentials import AzureKeyCredential from azure.core.credentials import AzureKeyCredential
from nonebot import on_command, logger from nonebot import on_command, logger
@@ -18,11 +21,12 @@ from nonebot.params import CommandArg
from nonebot.permission import SUPERUSER from nonebot.permission import SUPERUSER
from nonebot_plugin_alconna import on_alconna, MsgTarget from nonebot_plugin_alconna import on_alconna, MsgTarget
from nonebot_plugin_alconna.uniseg import UniMessage, UniMsg from nonebot_plugin_alconna.uniseg import UniMessage, UniMsg
import nonebot_plugin_localstore as store
from nonebot import get_driver from nonebot import get_driver
from .constants import * from .constants import *
from .metadata import metadata from .metadata import metadata
from .models import MarshoContext from .models import MarshoContext, MarshoTools
from .util import * from .util import *
driver = get_driver() driver = get_driver()
@@ -53,11 +57,18 @@ refresh_data_cmd = on_command("refresh_data", permission=SUPERUSER)
model_name = config.marshoai_default_model model_name = config.marshoai_default_model
context = MarshoContext() context = MarshoContext()
tools = MarshoTools()
token = config.marshoai_token token = config.marshoai_token
endpoint = config.marshoai_azure_endpoint endpoint = config.marshoai_azure_endpoint
client = ChatCompletionsClient(endpoint=endpoint, credential=AzureKeyCredential(token)) client = ChatCompletionsClient(endpoint=endpoint, credential=AzureKeyCredential(token))
target_list = [] # 记录需保存历史上下文的列表 target_list = [] # 记录需保存历史上下文的列表
@driver.on_startup
async def _preload_tools():
tools_dir = store.get_plugin_data_dir() / "tools"
os.makedirs(tools_dir, exist_ok=True)
tools.load_tools(Path(__file__).parent / "tools")
tools.load_tools(store.get_plugin_data_dir() / "tools")
@add_usermsg_cmd.handle() @add_usermsg_cmd.handle()
async def add_usermsg(target: MsgTarget, arg: Message = CommandArg()): async def add_usermsg(target: MsgTarget, arg: Message = CommandArg()):
@@ -77,6 +88,7 @@ async def add_assistantmsg(target: MsgTarget, arg: Message = CommandArg()):
@praises_cmd.handle() @praises_cmd.handle()
async def praises(): async def praises():
#await UniMessage(await tools.call("marshoai-weather.get_weather", {"location":"杭州"})).send()
await praises_cmd.finish(build_praises()) await praises_cmd.finish(build_praises())
@@ -110,7 +122,8 @@ async def load_context(target: MsgTarget, arg: Message = CommandArg()):
@resetmem_cmd.handle() @resetmem_cmd.handle()
async def resetmem(target: MsgTarget): async def resetmem(target: MsgTarget):
if [target.id, target.private] not in target_list: target_list.append([target.id, target.private]) if [target.id, target.private] not in target_list:
target_list.append([target.id, target.private])
context.reset(target.id, target.private) context.reset(target.id, target.private)
await resetmem_cmd.finish("上下文已重置") await resetmem_cmd.finish("上下文已重置")
@@ -169,7 +182,7 @@ async def marsho(target: MsgTarget, event: Event, text: Optional[UniMsg] = None)
"*你未设置自己的昵称。推荐使用'nickname [昵称]'命令设置昵称来获得个性化(可能)回答。" "*你未设置自己的昵称。推荐使用'nickname [昵称]'命令设置昵称来获得个性化(可能)回答。"
).send() ).send()
is_support_image_model = model_name.lower() in SUPPORT_IMAGE_MODELS is_support_image_model = model_name.lower() in SUPPORT_IMAGE_MODELS + config.marshoai_additional_image_models
is_reasoning_model = model_name.lower() in REASONING_MODELS is_reasoning_model = model_name.lower() in REASONING_MODELS
usermsg = [] if is_support_image_model else "" usermsg = [] if is_support_image_model else ""
for i in text: for i in text:
@@ -199,24 +212,45 @@ async def marsho(target: MsgTarget, event: Event, text: Optional[UniMsg] = None)
client=client, client=client,
model_name=model_name, model_name=model_name,
msg=context_msg + [UserMessage(content=usermsg)], msg=context_msg + [UserMessage(content=usermsg)],
tools=tools.get_tools_list()
) )
# await UniMessage(str(response)).send() # await UniMessage(str(response)).send()
choice = response.choices[0] choice = response.choices[0]
if ( if (choice["finish_reason"] == CompletionsFinishReason.STOPPED): # 当对话成功时将dict的上下文添加到上下文类中
choice["finish_reason"] == CompletionsFinishReason.STOPPED
): # 当对话成功时将dict的上下文添加到上下文类中
context.append( context.append(
UserMessage(content=usermsg).as_dict(), target.id, target.private UserMessage(content=usermsg).as_dict(), target.id, target.private
) )
context.append(choice.message.as_dict(), target.id, target.private) context.append(choice.message.as_dict(), target.id, target.private)
if [target.id, target.private] not in target_list: if [target.id, target.private] not in target_list:
target_list.append([target.id, target.private]) target_list.append([target.id, target.private])
await UniMessage(str(choice.message.content)).send(reply_to=True)
elif choice["finish_reason"] == CompletionsFinishReason.CONTENT_FILTERED: elif choice["finish_reason"] == CompletionsFinishReason.CONTENT_FILTERED:
await UniMessage("*已被内容过滤器过滤。请调整聊天内容后重试。").send( await UniMessage("*已被内容过滤器过滤。请调整聊天内容后重试。").send(reply_to=True)
reply_to=True
)
return return
await UniMessage(str(choice.message.content)).send(reply_to=True) elif choice["finish_reason"] == CompletionsFinishReason.TOOL_CALLS:
tool_msg = []
while choice.message.tool_calls != None:
tool_msg.append(AssistantMessage(tool_calls=response.choices[0].message.tool_calls))
for tool_call in choice.message.tool_calls:
if isinstance(tool_call, ChatCompletionsToolCall):
function_args = json.loads(tool_call.function.arguments.replace("'", '"'))
logger.info(f"调用函数 {tool_call.function.name} ,参数为 {function_args}")
await UniMessage(f"调用函数 {tool_call.function.name} ,参数为 {function_args}").send()
func_return = await tools.call(tool_call.function.name, function_args)
tool_msg.append(ToolMessage(tool_call_id=tool_call.id, content=func_return))
response = await make_chat(
client=client,
model_name=model_name,
msg = context_msg + [UserMessage(content=usermsg)] + tool_msg,
tools=tools.get_tools_list()
)
choice = response.choices[0]
context.append(
UserMessage(content=usermsg).as_dict(), target.id, target.private
)
#context.append(tool_msg, target.id, target.private)
context.append(choice.message.as_dict(), target.id, target.private)
await UniMessage(str(choice.message.content)).send(reply_to=True)
except Exception as e: except Exception as e:
await UniMessage(str(e) + suggest_solution(str(e))).send() await UniMessage(str(e) + suggest_solution(str(e))).send()
traceback.print_exc() traceback.print_exc()

View File

@@ -24,10 +24,15 @@ class ConfigModel(BaseModel):
marshoai_enable_support_image_tip: bool = True marshoai_enable_support_image_tip: bool = True
marshoai_enable_praises: bool = True marshoai_enable_praises: bool = True
marshoai_enable_time_prompt: bool = True marshoai_enable_time_prompt: bool = True
marshoai_enable_tools: bool = True
marshoai_azure_endpoint: str = "https://models.inference.ai.azure.com" marshoai_azure_endpoint: str = "https://models.inference.ai.azure.com"
marshoai_temperature: float | None = None marshoai_temperature: float | None = None
marshoai_max_tokens: int | None = None marshoai_max_tokens: int | None = None
marshoai_top_p: float | None = None marshoai_top_p: float | None = None
marshoai_additional_image_models: list = []
marshoai_tencent_secretid: str | None = None
marshoai_tencent_secretkey: str | None = None
config: ConfigModel = get_plugin_config(ConfigModel) config: ConfigModel = get_plugin_config(ConfigModel)

View File

@@ -0,0 +1,36 @@
import contextlib
import traceback
import json
from typing import Optional
from arclet.alconna import Alconna, Args, AllParam
from nonebot import on_command, logger
from nonebot.adapters import Message, Event
from nonebot.params import CommandArg
from nonebot.permission import SUPERUSER
from nonebot_plugin_alconna import on_alconna, MsgTarget
from nonebot_plugin_alconna.uniseg import UniMessage, UniMsg
from nonebot import get_driver
from .constants import *
from .metadata import metadata
from .models import MarshoContext
from .util_hunyuan import *
from .config import config
genimage_cmd = on_alconna(
Alconna(
"genimage",
Args["prompt?", str],
)
)
@genimage_cmd.handle()
async def genimage(event: Event, prompt=None):
if not prompt:
await genimage_cmd.finish("无提示词")
try:
result = generate_image(prompt)
url = json.loads(result)["ResultImage"]
await UniMessage.image(url=url).send()
except Exception as e:
# await genimage_cmd.finish(str(e))
traceback.print_exc()

View File

@@ -1,5 +1,12 @@
from .util import * from .util import *
from .config import config
import os
import re
import json
import importlib
#import importlib.util
import traceback
from nonebot import logger
class MarshoContext: class MarshoContext:
""" """
@@ -47,3 +54,76 @@ class MarshoContext:
if target_id not in target_dict: if target_id not in target_dict:
target_dict[target_id] = [] target_dict[target_id] = []
return target_dict[target_id] return target_dict[target_id]
class MarshoTools:
"""
Marsho 的工具类
"""
def __init__(self):
self.tools_list = []
self.imported_packages = {}
def load_tools(self, tools_dir):
"""
从指定路径加载工具包
"""
if not os.path.exists(tools_dir):
logger.error(f"工具集目录 {tools_dir} 不存在。")
return
for package_name in os.listdir(tools_dir):
package_path = os.path.join(tools_dir, package_name)
if os.path.isdir(package_path) and os.path.exists(os.path.join(package_path, '__init__.py')):
json_path = os.path.join(package_path, 'tools.json')
if os.path.exists(json_path):
try:
with open(json_path, 'r', encoding="utf-8") as json_file:
data = json.load(json_file)
for i in data:
self.tools_list.append(i)
# 导入包
spec = importlib.util.spec_from_file_location(package_name, os.path.join(package_path, "__init__.py"))
package = importlib.util.module_from_spec(spec)
spec.loader.exec_module(package)
self.imported_packages[package_name] = package
logger.info(f"成功加载工具包 {package_name}")
except json.JSONDecodeError as e:
logger.error(f"解码 JSON {json_path} 时发生错误: {e}")
except Exception as e:
logger.error(f"加载工具包时发生错误: {e}")
traceback.print_exc()
else:
logger.warning(f"在工具包 {package_path} 下找不到tools.json跳过加载。")
else:
logger.warning(f"{package_path} 不是有效的工具包路径,跳过加载。")
async def call(self, full_function_name: str, args: dict):
"""
调用指定的函数
"""
# 分割包名和函数名
parts = full_function_name.split("__")
if len(parts) == 2:
package_name = parts[0]
function_name = parts[1]
else:
logger.error("函数名无效")
if package_name in self.imported_packages:
package = self.imported_packages[package_name]
try:
function = getattr(package, function_name)
return await function(**args)
except AttributeError:
logger.error(f"函数 '{function_name}''{package_name}' 中找不到。")
except TypeError as e:
logger.error(f"调用函数 '{function_name}' 时发生错误: {e}")
else:
logger.error(f"工具包 '{package_name}' 未导入")
def get_tools_list(self):
if not self.tools_list or not config.marshoai_enable_tools:
return None
return self.tools_list

View File

@@ -0,0 +1,15 @@
import os
from datetime import datetime
from zhDateTime import DateTime
async def get_weather(location: str):
return f"{location}的温度是114514℃。"
async def get_current_env():
ver = os.popen("uname -a").read()
return str(ver)
async def get_current_time():
current_time = datetime.now().strftime("%Y.%m.%d %H:%M:%S")
current_lunar_date = (DateTime.now().to_lunar().date_hanzify()[5:])
time_prompt = f"现在的时间是{current_time},农历{current_lunar_date}"
return time_prompt

View File

@@ -0,0 +1,11 @@
[
{
"type": "function",
"function": {
"name": "marshoai-basic__get_current_time",
"description": "获取现在的时间。",
"parameters": {
}
}
}
]

View File

@@ -0,0 +1,39 @@
[
{
"type": "function",
"function": {
"name": "marshoai-basic__get_weather",
"description": "当你想查询指定城市的天气时非常有用。",
"parameters": {
"type": "object",
"properties": {
"location": {
"type": "string",
"description": "城市或县区,比如北京市、杭州市、余杭区等。"
}
}
},
"required": [
"location"
]
}
},
{
"type": "function",
"function": {
"name": "marshoai-basic__get_current_env",
"description": "获取当前的运行环境。",
"parameters": {
}
}
},
{
"type": "function",
"function": {
"name": "marshoai-basic__get_current_time",
"description": "获取现在的时间。",
"parameters": {
}
}
}
]

View File

@@ -0,0 +1,2 @@
async def write_memory(memory: str):
return ""

View File

@@ -0,0 +1,21 @@
[
{
"type": "function",
"function": {
"name": "marshoai-memory__write_memory",
"description": "当你想记住有关与你对话的人的一些信息的时候,调用此函数。",
"parameters": {
"type": "object",
"properties": {
"memory": {
"type": "string",
"description": "你想记住的内容,概括并保留关键内容。"
}
}
},
"required": [
"memory"
]
}
}
]

View File

@@ -40,7 +40,7 @@ async def get_image_b64(url):
return None return None
async def make_chat(client: ChatCompletionsClient, msg: list, model_name: str): async def make_chat(client: ChatCompletionsClient, msg: list, model_name: str, tools: list = None):
"""调用ai获取回复 """调用ai获取回复
参数: 参数:
@@ -50,6 +50,7 @@ async def make_chat(client: ChatCompletionsClient, msg: list, model_name: str):
return await client.complete( return await client.complete(
messages=msg, messages=msg,
model=model_name, model=model_name,
tools=tools,
temperature=config.marshoai_temperature, temperature=config.marshoai_temperature,
max_tokens=config.marshoai_max_tokens, max_tokens=config.marshoai_max_tokens,
top_p=config.marshoai_top_p, top_p=config.marshoai_top_p,
@@ -173,13 +174,6 @@ def get_prompt():
if config.marshoai_enable_praises: if config.marshoai_enable_praises:
praises_prompt = build_praises() praises_prompt = build_praises()
prompts += praises_prompt prompts += praises_prompt
if config.marshoai_enable_time_prompt:
current_time = datetime.now().strftime("%Y.%m.%d %H:%M:%S")
current_lunar_date = (
DateTime.now().to_lunar().date_hanzify()[5:]
) # 库更新之前使用切片
time_prompt = f"现在的时间是{current_time},农历{current_lunar_date}"
prompts += time_prompt
marsho_prompt = config.marshoai_prompt marsho_prompt = config.marshoai_prompt
spell = SystemMessage(content=marsho_prompt + prompts).as_dict() spell = SystemMessage(content=marsho_prompt + prompts).as_dict()
return spell return spell

View File

@@ -0,0 +1,31 @@
import json
import types
from tencentcloud.common import credential
from tencentcloud.common.profile.client_profile import ClientProfile
from tencentcloud.common.profile.http_profile import HttpProfile
from tencentcloud.common.exception.tencent_cloud_sdk_exception import TencentCloudSDKException
from tencentcloud.hunyuan.v20230901 import hunyuan_client, models
from .config import config
def generate_image(prompt: str):
cred = credential.Credential(config.marshoai_tencent_secretid, config.marshoai_tencent_secretkey)
# 实例化一个http选项可选的没有特殊需求可以跳过
httpProfile = HttpProfile()
httpProfile.endpoint = "hunyuan.tencentcloudapi.com"
# 实例化一个client选项可选的没有特殊需求可以跳过
clientProfile = ClientProfile()
clientProfile.httpProfile = httpProfile
client = hunyuan_client.HunyuanClient(cred, "ap-guangzhou", clientProfile)
req = models.TextToImageLiteRequest()
params = {
"Prompt": prompt,
"RspImgType": "url",
"Resolution": "1080:1920"
}
req.from_json_string(json.dumps(params))
# 返回的resp是一个TextToImageLiteResponse的实例与请求对象对应
resp = client.TextToImageLite(req)
# 输出json格式的字符串回包
return resp.to_json_string()

View File

@@ -1,7 +1,7 @@
[project] [project]
name = "nonebot-plugin-marshoai" name = "nonebot-plugin-marshoai"
dynamic = ["version"] dynamic = ["version"]
description = "Nonebot2插件调用Azure OpenAI服务实现猫娘聊天" description = "Nonebot2插件调用Azure OpenAI等AI服务实现猫娘聊天"
readme = "README.md" readme = "README.md"
requires-python = "<4.0,>=3.9" requires-python = "<4.0,>=3.9"
authors = [{ name = "Asankilp", email = "asankilp@outlook.com" }] authors = [{ name = "Asankilp", email = "asankilp@outlook.com" }]