Compare commits

...
19 Commits
Author SHA1 Message Date
shadowcz007 8887151bc8 Update avatar-agent-workflow.json 2024-10-17 12:08:33 +08:00
shadowcz007 059faa9f10 update 2024-10-17 09:15:04 +08:00
shadowcz007 3f3abbdc8c Update Agent.py 2024-10-16 23:05:22 +08:00
shadowcz007 6c8e94a388 Update avatar-agent-workflow.json 2024-10-16 23:05:20 +08:00
shadowcz007 6ef6dcedcb Update Agent.py 2024-10-16 11:28:05 +08:00
shadowcz007 9c57d5c860 修复bug 2024-10-16 10:50:35 +08:00
shadowcz007 f1ba9882b9 Update README.md 2024-10-15 21:30:19 +08:00
shadowcz007 0fc0f9c310 Create avatar-agent-workflow.json 2024-10-15 21:30:16 +08:00
shadowcz007 2a1831d1b0 Update SocialProfile.py 2024-10-15 21:20:49 +08:00
shadowcz007 dc139700ce update 2024-10-15 21:11:33 +08:00
shadowcz007 717011855f update 2024-10-15 17:44:11 +08:00
shadowcz007 e55bdb5987 Update SocialProfile.py 2024-10-15 17:31:33 +08:00
shadowcz007 9cb4ece33d update 2024-10-15 17:29:42 +08:00
shadowcz007 5b43eb80b6 update 2024-10-15 16:42:46 +08:00
shadowcz007 837c7b32a8 update 2024-10-15 16:01:01 +08:00
shadowcz007 63a32a739b update 2024-10-14 18:24:40 +08:00
shadowcz007 d8ee343e33 update 2024-10-14 17:58:05 +08:00
shadowcz007 a62c5f365d update 2024-10-14 17:30:44 +08:00
shadowcz007 3ab3dbd7ed init 2024-10-14 12:49:22 +08:00
9 changed files with 2464 additions and 286 deletions
+2
View File
@@ -10,6 +10,8 @@ For business cooperation, please contact email 389570357@qq.com
##### `最新`:
- AvatarGeneratorAgent [工作流示例](./workflow/avatar-agent-workflow.json)
- 新增[fal.ai](https://fal.ai/dashboard)的视频生成:Kling、RunwayGen3、LumaDreamMachine,[工作流下载](./workflow/video-all-in-one-test-workflow.json)
- 新增 SimulateDevDesignDiscussions,需要安装[swarm](https://github.com/openai/swarm)和[Comfyui-ChatTTS](https://github.com/shadowcz007/Comfyui-ChatTTS),[工作流下载](./workflow/swarm制作的播客节点workflow.json)
+33 -8
View File
@@ -1261,7 +1261,7 @@ logging.info('\033[91m ### Mixlab Nodes: \033[93mLoaded')
# print('\033[91m ### Mixlab Nodes: \033[93mLoaded')
try:
from .nodes.ChatGPT import SimulateDevDesignDiscussions,SiliconflowTextToImageNode,JsonRepair,ChatGPTNode,ShowTextForGPT,CharacterInText,TextSplitByDelimiter,SiliconflowFreeNode
from .nodes.ChatGPT import SiliconflowTextToImageNode,JsonRepair,ChatGPTNode,ShowTextForGPT,CharacterInText,TextSplitByDelimiter,SiliconflowFreeNode
logging.info('ChatGPT.available True')
NODE_CLASS_MAPPINGS_V = {
@@ -1271,9 +1271,7 @@ try:
"ShowTextForGPT":ShowTextForGPT,
"CharacterInText":CharacterInText,
"TextSplitByDelimiter":TextSplitByDelimiter,
"JsonRepair":JsonRepair,
"SimulateDevDesignDiscussions":SimulateDevDesignDiscussions
"JsonRepair":JsonRepair,
}
# 一个包含节点友好/可读的标题的字典
@@ -1284,9 +1282,7 @@ try:
"ShowTextForGPT":"Show Text ♾️MixlabApp",
"CharacterInText":"Character In Text",
"TextSplitByDelimiter":"Text Split By Delimiter",
"JsonRepair":"Json Repair",
"SimulateDevDesignDiscussions":"SimulateDevDesignDiscussions ♾️Mixlab Podcast"
"JsonRepair":"Json Repair",
}
@@ -1294,7 +1290,7 @@ try:
NODE_DISPLAY_NAME_MAPPINGS.update(NODE_DISPLAY_NAME_MAPPINGS_V)
except Exception as e:
logging.info('ChatGPT.available False')
logging.info('ChatGPT.available False',e)
try:
@@ -1474,4 +1470,33 @@ try:
except Exception as e:
logging.info('FalVideo.available False' )
try:
from .nodes.SocialProfile import NewSocialProfileNode,LoadSocialProfileNode
logging.info('SocialProfile.available')
# Update Node class mappings
NODE_CLASS_MAPPINGS['NewSocialProfileNode']=NewSocialProfileNode
NODE_CLASS_MAPPINGS['LoadSocialProfileNode']=LoadSocialProfileNode
NODE_DISPLAY_NAME_MAPPINGS["NewSocialProfileNode"]= "New Social Profile ♾️Mixlab"
NODE_DISPLAY_NAME_MAPPINGS["LoadSocialProfileNode"]= "Load Social Profile ♾️Mixlab"
except Exception as e:
logging.info('SocialProfile.available False' )
try:
from .nodes.Agent import AvatarGeneratorAgent,SimulateDevDesignDiscussions
logging.info('Agent.available')
NODE_CLASS_MAPPINGS['SimulateDevDesignDiscussions']=SimulateDevDesignDiscussions
NODE_CLASS_MAPPINGS['AvatarGeneratorAgent']=AvatarGeneratorAgent
NODE_DISPLAY_NAME_MAPPINGS["SimulateDevDesignDiscussions"]= "SimulateDevDesignDiscussions ♾️Mixlab Podcast"
NODE_DISPLAY_NAME_MAPPINGS["AvatarGeneratorAgent"]= "Avatar Generator Agent ♾️Mixlab"
except Exception as e:
logging.info('Agent.available False' )
logging.info('\033[93m -------------- \033[0m')
+892
View File
@@ -0,0 +1,892 @@
import openai
import time
import urllib.error
import re,json,os,string,random
import folder_paths
import hashlib
import sys
import importlib.util
import subprocess
import torch
import numpy as np
python = sys.executable
# Convert PIL to Tensor
def pil2tensor(image):
return torch.from_numpy(np.array(image).astype(np.float32) / 255.0).unsqueeze(0)
def is_installed(package, package_overwrite=None,auto_install=True):
is_has=False
try:
spec = importlib.util.find_spec(package)
is_has=spec is not None
except ModuleNotFoundError:
pass
package = package_overwrite or package
if spec is None:
if auto_install==True:
print(f"Installing {package}...")
# 清华源 -i https://pypi.tuna.tsinghua.edu.cn/simple
command = f'"{python}" -m pip install {package}'
result = subprocess.run(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True, env=os.environ)
is_has=True
if result.returncode != 0:
print(f"Couldn't install\nCommand: {command}\nError code: {result.returncode}")
is_has=False
else:
print(package+'## OK')
return is_has
if is_installed('json_repair'):
from json_repair import repair_json
# 从文本中提取json
def extract_json_strings(text):
json_strings = []
brace_level = 0
json_str = ''
in_json = False
for char in text:
if char == '{':
brace_level += 1
in_json = True
if in_json:
json_str += char
if char == '}':
brace_level -= 1
if in_json and brace_level == 0:
json_strings.append(json_str)
json_str = ''
in_json = False
return json_strings[0] if len(json_strings)>0 else "{}"
# text2json
def text_to_json(text):
text=extract_json_strings(text)
good_json_string = repair_json(text)
# 将 JSON 字符串解析为 Python 对象
data = json.loads(good_json_string)
return data
def save_to_json(file_path, data):
try:
with open(file_path, 'w', encoding='utf-8') as f:
json.dump(data, f, ensure_ascii=False, indent=4)
except Exception as e:
print(e)
def read_from_json(file_path):
data = None
try:
with open(file_path, 'r', encoding='utf-8') as f: # 使用 'r' 模式打开文件
data = json.load(f)
except Exception as e:
print('#read_from_json', e)
return None
return data
default_agent={
"user_name":"shadow",
"profile_id":"ML000",
"skills":"Design Hacker,Programmer,Architect,Experience Designer".split(",")
}
def create_default_file(agent_dir):
fp=os.path.join(agent_dir,'shadow.json')
if not os.path.exists(fp):
save_to_json(fp,default_agent)
def get_social_profile_dir():
try:
return folder_paths.get_folder_paths('agent')[0]
except:
agent_dir=os.path.join(folder_paths.models_dir, "agent")
if not os.path.exists(agent_dir):
os.makedirs(agent_dir, exist_ok=True)
create_default_file(agent_dir)
return agent_dir
def save_social_profile_config(agent_dir,file_name,data):
save_to_json(os.path.join(agent_dir,file_name),data)
def get_unique_hash(string):
hash_object = hashlib.sha1(string.encode())
unique_hash = hash_object.hexdigest()
return unique_hash
def generate_random_string(length):
letters = string.ascii_letters + string.digits
return ''.join(random.choice(letters) for _ in range(length))
class AnyType(str):
"""A special class that is always equal in not equal comparisons. Credit to pythongosssss"""
def __ne__(self, __value: object) -> bool:
return False
any_type = AnyType("*")
# 判断是否是azure服务
def is_azure_url(url):
pattern = r'.*\.azure\.com$'
if re.match(pattern, url):
return True
else:
return False
def azure_client(key,url):
client = openai.AzureOpenAI(
api_key=key,
# https://learn.microsoft.com/en-us/azure/ai-services/openai/reference#rest-api-versioning
api_version="2023-07-01-preview",
# https://learn.microsoft.com/en-us/azure/cognitive-services/openai/how-to/create-resource?pivots=web-portal#create-a-resource
azure_endpoint=url
)
return client
def openai_client(key,url):
client = openai.OpenAI(
api_key=key,
base_url=url
)
return client
def ZhipuAI_client(key):
try:
if is_installed('zhipuai')==True:
from zhipuai import ZhipuAI
except:
print("#install zhipuai error")
client = ZhipuAI(
api_key=key, # 填写您的 APIKey
)
return client
if is_installed('swarm','git+https://github.com/openai/swarm.git'):
from swarm import Swarm, Agent
def chat(client, model_name,messages,max_tokens=4096,temperature=0.6 ):
print('#chat',model_name,messages)
try_count = 0
while True:
try_count += 1
try:
if hasattr(client, "chat"):
response = client.chat.completions.create(
model=model_name,
messages=messages,
max_tokens=max_tokens,
temperature=temperature
)
else:
# 是llama的
response = client.create_chat_completion_openai_v1(
messages=messages,
# response_format={
# "type": "json_object",
# },
# temperature=0.7,
)
break
except openai.AuthenticationError as ex:
raise ex
except (urllib.error.HTTPError, openai.OpenAIError) as ex:
if try_count >= 3:
raise ex
time.sleep(3)
continue
# print(response.keys())
finish_reason = response.choices[0].finish_reason
if finish_reason != "stop":
raise RuntimeError("API finished with unexpected reason: " + finish_reason)
content=""
try:
content=response.choices[0].message.content
except:
content=response.choices[0].delta['content']
return content
llm_apis=[
{
"value": "https://api.openai.com/v1",
"label": "openai"
},
{
"value": "https://openai.api2d.net/v1",
"label": "api2d"
},
# {
# "value": "https://docs-test-001.openai.azure.com",
# "label": "https://docs-test-001.openai.azure.com"
# },
{
"value": "https://api.moonshot.cn/v1",
"label": "Kimi"
},
{
"value": "https://api.deepseek.com/v1",
"label": "DeepSeek-V2"
},
{
"value": "https://api.siliconflow.cn/v1",
"label": "SiliconCloud"
}]
llm_apis_dict = {api["label"]: api["value"] for api in llm_apis}
model_list=[
"gpt-4o",
"gpt-4o-2024-05-13",
"gpt-4",
"gpt-4-0314",
"gpt-4-0613",
"qwen-turbo",
"qwen-plus",
"qwen-long",
"qwen-max",
"qwen-max-longcontext",
"glm-4",
"glm-3-turbo",
"moonshot-v1-8k",
"moonshot-v1-32k",
"moonshot-v1-128k",
"deepseek-chat",
"Qwen/Qwen2-7B-Instruct",
"THUDM/glm-4-9b-chat",
"01-ai/Yi-1.5-9B-Chat-16K"
]
software_architect_agent = Agent(
name="Software Architect",
instructions='''用脱口秀的风格回答编程问题,简短且口语化。
输出格式
====
* 答案格式:`程序员:xxxxxxxxx`
示例
==
**输入:**
如何优化代码性能?
**输出:**
程序员:兄弟,先把那些循环里的debug信息删掉,CPU都快哭了。'''
)
designer_agent = Agent(
name="Designer",
instructions='''回答问题时,请扮演一位具有多年空间设计和用户体验设计经验的设计师。你的回答应当天马行空,但又富有深度,带有苏格拉底的思考方式,并且使用脱口秀的风格。回答要简短且非常口语化。格式如下:
设计师:\[回答内容\]
Output Format
=============
* 回答应当使用“设计师:\[回答内容\]”的格式。
* 回答应当简短、口语化,富有创意和深度。
Examples
========
**Example 1:**
主持人:你觉得未来的家会是什么样子?
设计师:未来的家?想象一下,房子会像变形金刚一样,随时变形满足你的需求。今天是健身房,明天是电影院,后天是游戏场。家不再是四面墙,而是一个随心所欲的魔法空间。
**Example 2:**
主持人:你怎么看待极简主义设计?
设计师:极简主义?就像吃寿司,去掉所有不必要的装饰,只留下最精华的部分。让空间呼吸,让心灵自由。
**Example 3:**
主持人:你觉得色彩在设计中有多重要?
设计师:色彩?哦,那可是设计的灵魂!就像人生中的调味料,一点红色让你激情澎湃,一点蓝色让你心如止水。色彩决定了空间的情绪基调。'''
)
# 问题生成
host_agent = Agent(
name="Host",
instructions='''
为播客的主持人生成4到5个问题,这些问题有些是针对设计师问的,有些是针对程序员问的。
* 主持人:你知道如何开发一款APP产品,从想法到上线吗?
* 主持人:站在设计师的角度,你怎么看?
* 主持人:不知道程序员又是怎么想的呢?
* 主持人:感谢大家的参与,今天收获蛮大的
Steps
=====
1. 确定问题的对象:设计师或程序员。
2. 根据对象设计相关的问题,确保问题的多样性和深度。
3. 整理问题,使其符合播客主持人的风格和语气。
Output Format
=============
问题列表,每个问题以“主持人:”开头,不要出现序号。
Examples
========
* 主持人:作为一名设计师,你是如何开始一个新项目的?
* 主持人:程序员在开发过程中遇到的最大挑战是什么?
* 主持人:设计师在团队协作中扮演什么角色?
* 主持人:程序员如何确保代码的质量和稳定性?
* 主持人:感谢大家的参与,今天的讨论非常有意义。
Notes
=====
* 确保问题针对不同的角色(设计师和程序员)。
* 保持问题的多样性,涵盖从项目开始到完成的各个阶段。
* 确保问题能引导出深入的讨论和见解。
''')
# 以下为固定提示词的LLM节点示例
class SimulateDevDesignDiscussions:
@classmethod
def INPUT_TYPES(cls):
return {
"required": {
"subject": ("STRING", {"multiline": True,"dynamicPrompts": False}),
"model": ( model_list,
{"default": model_list[0]}),
"api_url":(list(llm_apis_dict.keys()),
{"default": list(llm_apis_dict.keys())[0]}),
"seed": ("INT", {"default": 0, "min": 0, "max": 0xffffffffffffffff, "step": 1}),
},
"optional":{
"api_key":("STRING", {"forceInput": True,}),
"custom_model_name":("STRING", {"forceInput": True,}), #适合自定义model
"custom_api_url":("STRING", {"forceInput": True,}), #适合自定义model
},
}
RETURN_TYPES = ("STRING",)
RETURN_NAMES = ("text",)
FUNCTION = "generate_contextual_text"
CATEGORY = "♾️Mixlab/Agent"
INPUT_IS_LIST = False
OUTPUT_IS_LIST = (False,)
def generate_contextual_text(self,
subject,
model,
api_url,
seed,
api_key=None,
custom_model_name=None,
custom_api_url=None,
):
# 设置黄色文本的ANSI转义序列
YELLOW = "\033[33m"
# 重置文本颜色的ANSI转义序列
RESET = "\033[0m"
if custom_model_name!=None:
model=custom_model_name
api_url=llm_apis_dict[api_url] if api_url in llm_apis_dict else ""
if custom_api_url!=None:
api_url=custom_api_url
if api_key==None:
api_key="lm_studio"
print("api_key,api_url",api_key,api_url)
#
if is_azure_url(api_url):
client=azure_client(api_key,api_url)
else:
# 根据用户选择的模型,设置相应的接口和模型名称
if model == "glm-4" :
client = ZhipuAI_client(api_key) # 使用 Zhipuai 的接口
print('using Zhipuai interface')
else :
client = openai_client(api_key,api_url) # 使用 ChatGPT 的接口
# 以下为多智能体框架
client = Swarm(client=client)
# 定义两个代理:软件系统架构师和设计师
# 定义一个函数,用于转移问题到designer_agent
def transfer_to_designer_agent():
return designer_agent
# 将转移函数添加到软件系统架构师和设计师的函数列表中
software_architect_agent.functions.append(transfer_to_designer_agent)
response = client.run(agent=host_agent, messages=[{
"role":"user",
"content":f"主题是‘{subject}’"
}],model_override=model)
content=response.messages[-1]["content"]
print(f"{YELLOW}{content}{RESET}")
texts=content.split("\n")
# texts='''
# 主持人:你知道如何开发一款APP产品,从想法到上线吗?
# 主持人:站在设计师的角度,你怎么看?
# 主持人:不知道程序员又是怎么想的呢?
# 主持人:感谢大家的参与,今天收获蛮大的
# '''.split("\n")
messages=[]
texts = [text.strip() for text in texts if text.strip()]
result=[]
for text in texts:
messages.append({
"role": "user",
"content": text
})
# 运行客户端,使用软件系统架构师作为初始代理
response = client.run(agent=software_architect_agent, messages=messages,model_override=model)
print(f"{text}")
result.append(text)
# 输出最后一个响应消息的内容
content=response.messages[-1]["content"]
print(f"{YELLOW}{content}{RESET}")
result.append(content)
messages.append({
"role":"assistant",
"content":content
})
return ("\n".join(result),)
class AvatarGeneratorAgent:
@classmethod
def INPUT_TYPES(cls):
return {
"required": {
"subject": ("STRING", {"multiline": True,"dynamicPrompts": False}),
"social_profile":("STRING", {"forceInput": True}),
"model": ( model_list,
{"default": model_list[0]}),
"api_url":(list(llm_apis_dict.keys()),
{"default": list(llm_apis_dict.keys())[0]}),
"seed": ("INT", {"default": 0, "min": 0, "max": 0xffffffffffffffff, "step": 1}),
},
"optional":{
"api_key":("STRING", {"forceInput": True,}),
"custom_model_name":("STRING", {"forceInput": True,}), #适合自定义model
"custom_api_url":("STRING", {"forceInput": True,}), #适合自定义model
},
}
RETURN_TYPES = ("STRING","STRING","STRING","STRING",)
RETURN_NAMES = ("subject","result","task_desc","new_skill",)
FUNCTION = "run"
CATEGORY = "♾️Mixlab/Agent"
def run(self, subject, social_profile, model,
api_url, seed, api_key=None, custom_model_name=None, custom_api_url=None):
# 设置黄色文本的ANSI转义序列
YELLOW = "\033[33m"
# 重置文本颜色的ANSI转义序列
RESET = "\033[0m"
if custom_model_name!=None:
model=custom_model_name
api_url=llm_apis_dict[api_url] if api_url in llm_apis_dict else ""
if custom_api_url!=None:
api_url=custom_api_url
if api_key==None:
api_key="lm_studio"
print("api_key,api_url",api_key,api_url)
#
if is_azure_url(api_url):
client=azure_client(api_key,api_url)
else:
# 根据用户选择的模型,设置相应的接口和模型名称
if model == "glm-4" :
client = ZhipuAI_client(api_key) # 使用 Zhipuai 的接口
print('using Zhipuai interface')
else :
client = openai_client(api_key,api_url) # 使用 ChatGPT 的接口
# 以下为多智能体框架
client = Swarm(client=client)
# 定义1个代理:生成器
# instructions
def generator_instructions(context_variables):
# user = context_variables.get("name", "User")
user=json.dumps(context_variables)
return f'''根据用户的背景信息{user},生成角色新的技能挑战,欢迎并根据提供的信息创意性地整合和演变技能挑战,包含任务控制在3个以内。'''+'''
步骤
==
1. **欢迎用户**
* 欢迎用户并提及其用户名。
2. **生成技能挑战**
* 根据用户的技能,设计创意性的技能挑战。
* 每个挑战需要整合用户的多个技能。
* 挑战数量控制在3个以内。
输出格式
====
* 输出格式为口语化的一个段落,不要有换行。
示例1
==
**输入:**
{
"user_name": "shadow",
"profile_id": "ML000",
"skills": ["Design Hacker", "Programmer", "Architect", "Experience Designer", "设计黑客"]
}
信息:Mothbox是一款低成本、高性能的昆虫监测设备,旨在帮助野外生物学家在丛林深处进行部署,同时也适合在家中研究生物多样性。所有物理设计、电子原理图、Pi脚本和昆虫识别的人工智能都是免费开源的,用户可以自行构建、分享和改进。Mothbox利用超高分辨率传感器和开源AI脚本进行昆虫监测,提供高度本地化的环境健康数据,特别适用于研究飞蛾和甲虫等高度多样化的昆虫。
**输出:**
欢迎shadow!我们很高兴你对Mothbox感兴趣。根据你的技能,我们为你设计了以下创意性技能挑战:第一个挑战是**设计和构建一个模块化的Mothbox外壳**,利用你的建筑师和设计黑客技能,创造一个可以适应不同环境和需求的模块化外壳设计。挑战二是**开发一个用户友好的界面**,作为一名程序员和体验设计师,设计一个直观的用户界面,使用户可以轻松地配置和监测Mothbox。挑战三是**优化昆虫识别算法**:结合你的程序员和设计黑客技能,改进现有的开源AI脚本,提高昆虫识别的准确性和速度。我们期待看到你如何运用你的多重技能来挑战和改进Mothbox!
示例2
==
**输入:**
{
"user_name": "meadow",
"profile_id": "ML002",
"skills": ["体验设计师", "作家"]
}
信息:苹果发布新的iPad mini,AI功能来了
**输出:**
欢迎meadow!我们很高兴你对苹果发布的新的iPad mini感兴趣。根据你的技能,我们为你设计了以下创意性技能挑战:第一个挑战是**设计一个AI驱动的用户体验测试平台**:利用你的体验设计师技能,创建一个平台,使用户可以通过iPad mini的AI功能进行用户体验测试,收集和分析数据,优化应用和服务。挑战二是**撰写一篇关于AI在移动设备上应用的深度文章**:作为一名作家,撰写一篇详细的文章,探讨AI功能如何改变了iPad mini的使用体验,并预测未来的发展趋势。挑战三是**开发一个互动的iPad mini用户指南**:结合你的体验设计师和作家技能,设计并编写一个互动的用户指南,使新用户可以轻松上手iPad mini,充分利用其AI功能。我们期待看到你如何运用你的多重技能来挑战和改进iPad mini的用户体验!
'''.strip()
def skills_instructions(context_variables):
new_skill = context_variables.get("new_skill", "")
user=json.dumps(context_variables)
return f'''根据用户信息{user}和新技能{new_skill},判断是否需要更新用户的技能树。'''+'''
如果需要更新,输出技能树中需要添加的新标签`new_tag`;如果不需要更新,则输出`new_tag`为空。
* 用户信息 (`user`): 包括用户名、配置文件ID和现有技能。
* 新技能 (`new_skill`): 需要判断的新技能。
Steps
=====
1. 检查新技能是否已经存在于用户的技能列表中。
2. 如果新技能存在,`new_tag`为空。
3. 如果新技能不存在,`new_tag`为新技能。
Output Format
=============
```
{
"new_tag": "[new_skill or empty string]"
}
```
Examples
========
**Example 1**
* **Input:**
```
{
"user": {
"user_name": "shadow",
"profile_id": "ML000",
"skills": ["Design Hacker", "Programmer", "Architect", "Experience Designer"]
},
"new_skill": "设计黑客"
}
```
* **Reasoning:**
新技能"设计黑客"不在现有技能列表中,因此需要更新技能树。
* **Output:**
```
{
"new_tag": "设计黑客"
}
```
**Example 2**
* **Input:**
```
{
"user": {
"user_name": "shadow",
"profile_id": "ML000",
"skills": ["Design Hacker", "Programmer", "Architect", "Experience Designer"]
},
"new_skill": "Programmer"
}
```
* **Reasoning:**
新技能"Programmer"已经在现有技能列表中,因此不需要更新技能树。
* **Output:**
```
{
"new_tag": ""
}
```
'''
# 用于更新用户信息
def update_account_details(context_variables: dict):
profile_id = context_variables.get("profile_id", None)
user_name = context_variables.get("user_name", None)
skills = context_variables.get("skills", None)
file_name=context_variables.get('file_name','agent.json')
if skills:
skills=",".join(skills)
print(f"Account Details: {user_name} {profile_id} {skills}")
#
save_social_profile_config(get_social_profile_dir(),file_name,context_variables)
return "Success"
generator_agent = Agent(
name="generator_agent",
instructions=generator_instructions,
# functions=[update_account_details],
)
# 用于判断是否需要更新
skills_agent = Agent(
name="skills_agent",
instructions=skills_instructions,
functions=[update_account_details],
)
# dict
context_variables = json.loads(social_profile)
response = client.run(
messages=[{"role": "user", "content":subject}],
agent=generator_agent,
context_variables=context_variables,
model_override=model
)
result=response.messages[-1]["content"]
print(f"{YELLOW}{result}{RESET}")
# 答案生成
def answer_instructions(context_variables):
# user = context_variables.get("name", "User")
user=json.dumps(context_variables)
return '''根据提供的挑战任务,提炼任务的关键词,生成任务的图像文字描述。然后,结合用户信息'''+user+'''里的技能信息,构建一个技能树,给完成任务设计一个奖励,这个奖励是一个新的技能标签,为这颗技能树提供新的分支或者是加粗原有的技能。用JSON格式输出新的技能标签和图像的文字描述:
Steps
=====
1. 提炼任务的关键词。
2. 根据关键词生成图像文字描述。
3. 结合用户的技能信息,构建技能树。
4. 设计奖励的新技能标签。
5. 用JSON格式输出新的技能标签和图像的文字描述。
Output Format
=============
JSON格式,包含新的技能标签和图像文字描述。
Examples
========
**Input:**
```
{
"user_name": "shadow",
"profile_id": "ML000",
"skills": ["Design Hacker", "Programmer", "Architect", "Experience Designer", "设计黑客"]
}
挑战任务:设计模块化Mothbox外壳,开发用户友好的数据分析平台,并将美食数据分析技术应用于昆虫数据解析,提升设备功能和表现。
```
**Output:**
```
{
"skill": "Environmental Data Analyst",
"image": "设计模块化Mothbox外壳,开发用户友好数据分析平台,结合美食数据分析技术应用于环保领域。"
}
```
Notes
=====
* 关键词应包括:模块化外壳、数据分析平台、美食数据分析、环境健康、昆虫监测。
* 奖励的新技能标签应与任务相关,并补充现有技能树。'''.strip()
answer_agent = Agent(
name="Answer",
instructions=answer_instructions)
response = client.run(
messages=[{"role": "user", "content": result}],
agent=answer_agent,
context_variables=context_variables,
model_override=model
)
content=response.messages[-1]["content"]
answer_json=text_to_json(content)
print(f"{YELLOW}{content}{RESET}")
task_desc=""
new_skill=""
if "skill" in answer_json and 'image' in answer_json:
context_variables['new_skill']=answer_json['skill']
new_skill=answer_json['skill']
task_desc=answer_json['image']
print(f"{YELLOW}{task_desc}{RESET}")
response = client.run(
messages=[{"role": "user", "content": "请判断是否需要更新我的数字分身信息"}],
agent=skills_agent,
context_variables=context_variables,
model_override=model
)
content=response.messages[-1]["content"]
print(f"{YELLOW}{content}{RESET}")
# 重新改写subject - > 提问
prompt='''用口语化的表达改写文本,开头使用“我有个新话题,是”。
确保改写后的内容自然、流畅。
Steps
=====
1. 阅读并理解原文本。
2. 将文本改写成口语化的表达,注意语气和句式。
3. 在改写后的文本开头加上“我有个新话题,是”。
Output Format
=============
输出格式为段落,使用口语化的表达,开头为“我有个新话题,是”。
Examples
========
**Input:**
今天的天气真好,阳光明媚,适合出去散步。
**Output:**
我有个新话题,是今天的天气真好,阳光明媚,特别适合出去散步。
**Input:**
读书可以增长知识,开阔视野。
**Output:**
我有个新话题,是读书可以增长知识,还能开阔视野。'''
# 改写
subject_agent = Agent(
name="subject_agent",
instructions=prompt,
)
response = client.run(
messages=[{"role": "user", "content":subject}],
agent=subject_agent,
model_override=model
)
# 改写
subject=response.messages[-1]["content"]
print(f"{YELLOW}{subject}{RESET}")
return (subject,result,task_desc,new_skill,)
+53 -275
View File
@@ -1,6 +1,4 @@
import openai
from swarm import Swarm, Agent
import time
import urllib.error
import re,json,os,string,random
@@ -21,30 +19,6 @@ python = sys.executable
def pil2tensor(image):
return torch.from_numpy(np.array(image).astype(np.float32) / 255.0).unsqueeze(0)
# 从文本中提取json
def extract_json_strings(text):
json_strings = []
brace_level = 0
json_str = ''
in_json = False
for char in text:
if char == '{':
brace_level += 1
in_json = True
if in_json:
json_str += char
if char == '}':
brace_level -= 1
if in_json and brace_level == 0:
json_strings.append(json_str)
json_str = ''
in_json = False
return json_strings[0] if len(json_strings)>0 else "{}"
def is_installed(package, package_overwrite=None,auto_install=True):
is_has=False
try:
@@ -73,6 +47,58 @@ def is_installed(package, package_overwrite=None,auto_install=True):
return is_has
if is_installed('json_repair'):
from json_repair import repair_json
# 从文本中提取json
def extract_json_strings(text):
json_strings = []
brace_level = 0
json_str = ''
in_json = False
for char in text:
if char == '{':
brace_level += 1
in_json = True
if in_json:
json_str += char
if char == '}':
brace_level -= 1
if in_json and brace_level == 0:
json_strings.append(json_str)
json_str = ''
in_json = False
return json_strings[0] if len(json_strings)>0 else "{}"
# text2json
def text_to_json(text):
text=extract_json_strings(text)
good_json_string = repair_json(text)
# 将 JSON 字符串解析为 Python 对象
data = json.loads(good_json_string)
return data
def save_to_json(file_path, data):
try:
with open(file_path, 'w', encoding='utf-8') as f:
json.dump(data, f, ensure_ascii=False, indent=4)
except Exception as e:
print(e)
def read_from_json(file_path):
data = None
try:
with open(file_path, 'r', encoding='utf-8') as f: # 使用 'r' 模式打开文件
data = json.load(f)
except Exception as e:
print('#read_from_json', e)
return None
return data
# def is_installed(package):
@@ -212,8 +238,6 @@ def get_llama_path():
# return llm
if is_installed('json_repair'):
from json_repair import repair_json
def chat(client, model_name,messages,max_tokens=4096,temperature=0.6 ):
@@ -803,7 +827,7 @@ class JsonRepair:
# OUTPUT_NODE = True
OUTPUT_IS_LIST = (False,False,)
CATEGORY = "♾️Mixlab/GPT"
CATEGORY = "♾️Mixlab/Utils"
def run(self, json_string,key="",json_string2=None):
@@ -839,249 +863,3 @@ class JsonRepair:
json_str_with_chinese = json.dumps(data, ensure_ascii=False)
return (json_str_with_chinese,v,)
# 以下为固定提示词的LLM节点示例
class SimulateDevDesignDiscussions:
@classmethod
def INPUT_TYPES(cls):
model_list=[
"gpt-4o",
"gpt-4o-2024-05-13",
"gpt-4",
"gpt-4-0314",
"gpt-4-0613",
"qwen-turbo",
"qwen-plus",
"qwen-long",
"qwen-max",
"qwen-max-longcontext",
"glm-4",
"glm-3-turbo",
"moonshot-v1-8k",
"moonshot-v1-32k",
"moonshot-v1-128k",
"deepseek-chat",
"Qwen/Qwen2-7B-Instruct",
"THUDM/glm-4-9b-chat",
"01-ai/Yi-1.5-9B-Chat-16K"
]
return {
"required": {
"subject": ("STRING", {"multiline": True,"dynamicPrompts": False}),
"model": ( model_list,
{"default": model_list[0]}),
"api_url":(list(llm_apis_dict.keys()),
{"default": list(llm_apis_dict.keys())[0]}),
},
"optional":{
"api_key":("STRING", {"forceInput": True,}),
"custom_model_name":("STRING", {"forceInput": True,}), #适合自定义model
"custom_api_url":("STRING", {"forceInput": True,}), #适合自定义model
},
}
RETURN_TYPES = ("STRING",)
RETURN_NAMES = ("text",)
FUNCTION = "generate_contextual_text"
CATEGORY = "♾️Mixlab/GPT"
INPUT_IS_LIST = False
OUTPUT_IS_LIST = (False,)
def generate_contextual_text(self,
subject,
model,
api_url,
api_key=None,
custom_model_name=None,
custom_api_url=None,
):
# 设置黄色文本的ANSI转义序列
YELLOW = "\033[33m"
# 重置文本颜色的ANSI转义序列
RESET = "\033[0m"
if custom_model_name!=None:
model=custom_model_name
api_url=llm_apis_dict[api_url] if api_url in llm_apis_dict else ""
if custom_api_url!=None:
api_url=custom_api_url
if api_key==None:
api_key="lm_studio"
print("api_key,api_url",api_key,api_url)
#
if is_azure_url(api_url):
client=azure_client(api_key,api_url)
else:
# 根据用户选择的模型,设置相应的接口和模型名称
if model == "glm-4" :
client = ZhipuAI_client(api_key) # 使用 Zhipuai 的接口
print('using Zhipuai interface')
else :
client = openai_client(api_key,api_url) # 使用 ChatGPT 的接口
# 以下为多智能体框架
client = Swarm(client=client)
# 定义两个代理:软件系统架构师和设计师
software_architect_agent = Agent(
name="Software Architect",
instructions='''用脱口秀的风格回答编程问题,简短且口语化。
输出格式
====
* 答案格式:`程序员:xxxxxxxxx`
示例
==
**输入:**
如何优化代码性能?
**输出:**
程序员:兄弟,先把那些循环里的debug信息删掉,CPU都快哭了。'''
)
designer_agent = Agent(
name="Designer",
instructions='''回答问题时,请扮演一位具有多年空间设计和用户体验设计经验的设计师。你的回答应当天马行空,但又富有深度,带有苏格拉底的思考方式,并且使用脱口秀的风格。回答要简短且非常口语化。格式如下:
设计师:\[回答内容\]
Output Format
=============
* 回答应当使用“设计师:\[回答内容\]”的格式。
* 回答应当简短、口语化,富有创意和深度。
Examples
========
**Example 1:**
主持人:你觉得未来的家会是什么样子?
设计师:未来的家?想象一下,房子会像变形金刚一样,随时变形满足你的需求。今天是健身房,明天是电影院,后天是游戏场。家不再是四面墙,而是一个随心所欲的魔法空间。
**Example 2:**
主持人:你怎么看待极简主义设计?
设计师:极简主义?就像吃寿司,去掉所有不必要的装饰,只留下最精华的部分。让空间呼吸,让心灵自由。
**Example 3:**
主持人:你觉得色彩在设计中有多重要?
设计师:色彩?哦,那可是设计的灵魂!就像人生中的调味料,一点红色让你激情澎湃,一点蓝色让你心如止水。色彩决定了空间的情绪基调。'''
)
# 定义一个函数,用于转移问题到designer_agent
def transfer_to_designer_agent():
return designer_agent
# 将转移函数添加到软件系统架构师和设计师的函数列表中
software_architect_agent.functions.append(transfer_to_designer_agent)
# 问题生成
host_agent = Agent(
name="Host",
instructions='''
为播客的主持人生成4到5个问题,这些问题有些是针对设计师问的,有些是针对程序员问的。
* 主持人:你知道如何开发一款APP产品,从想法到上线吗?
* 主持人:站在设计师的角度,你怎么看?
* 主持人:不知道程序员又是怎么想的呢?
* 主持人:感谢大家的参与,今天收获蛮大的
Steps
=====
1. 确定问题的对象:设计师或程序员。
2. 根据对象设计相关的问题,确保问题的多样性和深度。
3. 整理问题,使其符合播客主持人的风格和语气。
Output Format
=============
问题列表,每个问题以“主持人:”开头,不要出现序号。
Examples
========
* 主持人:作为一名设计师,你是如何开始一个新项目的?
* 主持人:程序员在开发过程中遇到的最大挑战是什么?
* 主持人:设计师在团队协作中扮演什么角色?
* 主持人:程序员如何确保代码的质量和稳定性?
* 主持人:感谢大家的参与,今天的讨论非常有意义。
Notes
=====
* 确保问题针对不同的角色(设计师和程序员)。
* 保持问题的多样性,涵盖从项目开始到完成的各个阶段。
* 确保问题能引导出深入的讨论和见解。
''')
response = client.run(agent=host_agent, messages=[{
"role":"user",
"content":f"主题是‘{subject}’"
}],model_override=model)
content=response.messages[-1]["content"]
print(f"{YELLOW}{content}{RESET}")
texts=content.split("\n")
# texts='''
# 主持人:你知道如何开发一款APP产品,从想法到上线吗?
# 主持人:站在设计师的角度,你怎么看?
# 主持人:不知道程序员又是怎么想的呢?
# 主持人:感谢大家的参与,今天收获蛮大的
# '''.split("\n")
messages=[]
texts = [text.strip() for text in texts if text.strip()]
result=[]
for text in texts:
messages.append({
"role": "user",
"content": text
})
# 运行客户端,使用软件系统架构师作为初始代理
response = client.run(agent=software_architect_agent, messages=messages,model_override=model)
print(f"{text}")
result.append(text)
# 输出最后一个响应消息的内容
content=response.messages[-1]["content"]
print(f"{YELLOW}{content}{RESET}")
result.append(content)
messages.append({
"role":"assistant",
"content":content
})
return ("\n".join(result),)
+7 -1
View File
@@ -684,7 +684,7 @@ class JoinWithDelimiter:
def INPUT_TYPES(s):
return {"required": {
"text_list": (any_type,),
"delimiter":(["newline","comma","backslash","space"],),
"delimiter":(["newline","comma","backslash","space","colon"],),
},
}
@@ -707,7 +707,13 @@ class JoinWithDelimiter:
delimiter='\\'
elif delimiter=='space':
delimiter=' '
elif delimiter=='colon':
delimiter=":"
t=''
if isinstance(text_list, list):
t=join_with_(text_list,delimiter)
# 如果只有一个元素,则末尾补充delimiter ,尤其适合制作播客的 name: 这种前缀
if len(text_list)==1:
t=t+delimiter
return (t,)
+155
View File
@@ -0,0 +1,155 @@
# 用于定义社交名片
import json,os,re
import folder_paths
def save_to_json(file_path, data):
try:
print(f"Saving data to {file_path}") # 调试信息
with open(file_path, 'w', encoding='utf-8') as f:
json.dump(data, f, ensure_ascii=False, indent=4)
print("Data saved successfully.") # 调试信息
except Exception as e:
print('#save_to_json', e)
def read_from_json(file_path):
data = None
try:
with open(file_path, 'r', encoding='utf-8') as f: # 使用 'r' 模式打开文件
data = json.load(f)
except Exception as e:
print('#read_from_json', e)
return None
return data
default_agent={
"user_name":"shadow",
"profile_id":"ML000",
"skills":"Design Hacker,Programmer,Architect,Experience Designer".split(",")
}
def create_default_file(agent_dir):
fp=os.path.join(agent_dir,'shadow.json')
if not os.path.exists(fp):
save_to_json(fp,default_agent)
def get_social_profile_dir():
try:
return folder_paths.get_folder_paths('agent')[0]
except:
agent_dir=os.path.join(folder_paths.models_dir, "agent")
if not os.path.exists(agent_dir):
os.makedirs(agent_dir, exist_ok=True)
create_default_file(agent_dir)
return agent_dir
def list_all_json_files(directory_path):
json_files = []
try:
for filename in os.listdir(directory_path):
if filename.endswith('.json'):
json_files.append(filename)
except Exception as e:
print(f"An error occurred: {e}")
return json_files
def read_social_profiles():
agent_dir=get_social_profile_dir()
files=list_all_json_files(agent_dir)
if len(files)==0:
create_default_file(agent_dir)
files=list_all_json_files(agent_dir)
return files
def save_social_profile_config(agent_dir,file_name,data):
save_to_json(os.path.join(agent_dir,file_name),data)
agent_dir=get_social_profile_dir()
# print('Watcher:',config_json)
class NewSocialProfileNode:
@classmethod
def INPUT_TYPES(s):
user=default_agent
return {
"required": {
"user_name": ("STRING", {"forceInput": False, "default": user['user_name']}),
"profile_id": ("STRING", {"forceInput": False, "default": user['profile_id']}),
"skills": ("STRING", {"forceInput": False, "multiline": True, "default": ",".join(user['skills'])}),
"file_name": ("STRING", {"forceInput": False, "default": "agent"}),
},
}
# INPUT_IS_LIST = False
RETURN_TYPES = ("STRING",)
RETURN_NAMES = ("social_profile(json_string)",)
FUNCTION = "run"
# OUTPUT_IS_LIST = (False,)
CATEGORY = "♾️Mixlab/Agent"
def run(self, user_name, profile_id, skills,file_name):
# 使用正则表达式匹配英文和中文逗号
skills_list = [skill.strip() for skill in re.split(r'[,,]', skills)]
# 创建社交名片的JSON对象
social_profile = {
"user_name": user_name,
"profile_id": profile_id,
"skills": skills_list,
}
# 将社交名片转换为JSON字符串
json_string = json.dumps(social_profile, ensure_ascii=False)
save_social_profile_config(agent_dir,file_name+'.json',social_profile)
# 返回JSON字符串和一个示例值
return (json_string,)
class LoadSocialProfileNode:
@classmethod
def INPUT_TYPES(s):
files=read_social_profiles()
return {
"required": {
"file_name": ( files,
{"default": files[0]}),
"seed": ("INT", {"default": 0, "min": 0, "max": 0xffffffffffffffff, "step": 1}),
},
}
# INPUT_IS_LIST = False
RETURN_TYPES = ("STRING",)
RETURN_NAMES = ("social_profile(json_string)",)
FUNCTION = "run"
# OUTPUT_IS_LIST = (False,)
CATEGORY = "♾️Mixlab/Agent"
def run(self,file_name,seed):
social_profile=read_from_json(os.path.join(agent_dir,file_name))
# print("#read_from_json",os.path.join(agent_dir,file_name),social_profile)
if social_profile==None:
return ("",)
social_profile['file_name']=file_name
# 将社交名片转换为JSON字符串
json_string = json.dumps(social_profile, ensure_ascii=False)
# 返回JSON字符串和一个示例值
return (json_string,)
+1 -1
View File
@@ -667,7 +667,7 @@ class CreateJsonNode:
FUNCTION = "run"
CATEGORY = "♾️Mixlab/Output"
CATEGORY = "♾️Mixlab/Utils"
OUTPUT_NODE = True
INPUT_IS_LIST = False
+1 -1
View File
@@ -292,7 +292,7 @@ class ScenedetectNode_:
RETURN_TYPES = ("SCENE_VIDEO","SCENE_", "INT","INT",)
RETURN_NAMES = ("scenes_video","scenes","scene_len","total_frames",)
OUTPUT_IS_LIST = (False,False,False,)
# OUTPUT_IS_LIST = (False,False,False,)
FUNCTION = "run"
CATEGORY = "♾️Mixlab/Video"
File diff suppressed because it is too large Load Diff