1 line
15 KiB
JSON
1 line
15 KiB
JSON
{"repo": "867888660/linko", "files": {"Nodes/DeepSeekR1.py": {"421b3247331ea4e06580123bc23ee163b3f867a1": {"t": 1785746492.6092246, "n": 6399, "h": "95278d666182a368", "c": "import json\nimport re\nimport http.client\nimport base64\nfrom openai import OpenAI\nimport os\nfrom pathlib import Path\n#**Define the number of outputs and inputs\nOutPutNum = 1\nInPutNum = 0\n#**Define the number of outputs and inputs\nFunctionIntroduction='组件功能(简述代码整体功能)\\\\n这是一个基于 DeepSeek API 的大语言模型节点,支持文本和图像输入的多模态对话功能。该组件可以处理用户的文本提示和图像文件,通过 DeepSeek Reasoner 模型生成智能回复。\\\\n\\\\n代码功能摘要(概括核心算法或主要处理步骤)\\\\n核心功能包括图像文件的 Base64 编码转换、多模态消息构建、DeepSeek API 调用、响应内容的 JSON 格式化处理,以及输出结果的结构化封装。支持原始文本和 JSON 两种输出格式。\\\\n\\\\n参数\\\\n```yaml\\\\ninputs: []\\\\noutputs:\\\\n - name: OutPut1\\\\n type: string\\\\n description: 模型生成的回复内容\\\\n```\\\\n\\\\n运行逻辑\\\\n- 清空并重新初始化输出数组\\\\n- 遍历输入节点,检测文件路径类型的输入\\\\n- 将图像文件转换为 Base64 编码格式\\\\n- 根据原始文本选择器处理导出提示词\\\\n- 构建包含文本和图像的多模态消息数组\\\\n- 使用 DeepSeek API 密钥初始化 OpenAI 客户端\\\\n- 限制最大令牌数不超过 8192\\\\n- 调用 deepseek-reasoner 模型进行对话生成\\\\n- 提取 API 响应中的内容文本\\\\n- 根据输出格式选择器处理响应内容\\\\n- 如果选择 JSON 格式,则解析并格式化 JSON 数据\\\\n- 将处理后的结果分配给相应的输出节点\\\\n- 记录 API 调用的令牌使用统计信息\\\\n- 返回包含生成内容和统计信息的输出数组'\n\n#**Initialize Outputs and Inputs arrays and assign names directly\nOutputs = [{'Num': None, 'Kind': None,'Boolean':False, 'Id': f'Output{i + 1}', 'Context': None,'name':f'OutPut{i + 1}','Link':0,'Description':'answer'} for i in range(OutPutNum)]\nInputs = [{'Num': None, 'Kind': None, 'Id': f'Input{i + 1}', 'Context': None, 'Isnecessary': True,'name':f'Input{i + 1}','Link':0,'IsLabel':False} for i in range(InPutNum)]\n#**Initialize Outputs and Inputs arrays and assign names directly\nNodeKind = 'LLm'\nLable = [{'Id': 'Label1', 'Kind': 'None'}]\n\n#**Assign properties to Inputs\n\nfor output in Outputs:\n output['Kind'] = 'String'\n\nfor input in Inputs:\n input['Kind'] = 'String'\n#**Assign properties to Inputs\n\ndef image_to_base64(image_path):\n with open(image_path, \"rb\") as image_file:\n encoded_image = base64.b64encode(image_file.read())\n return encoded_image.decode('utf-8')\n\ndef get_llm_api_key():\n \"\"\"从环境变量读取当前组件的 API 密钥\"\"\"\n component_name = Path(__file__).stem\n try:\n edit_path = Path(__file__).parent.parent / \"Edit\" / \"Edit.json\"\n if edit_path.exists():\n with open(edit_path, 'r', encoding='utf-8') as f:\n config = json.load(f)\n llm_mappings = config.get('llmMappings', {})\n key_name = None\n for k, v in llm_mappings.items():\n if k.lower() == component_name.lower():\n key_name = v\n break\n if key_name:\n api_key = os.getenv(key_name, \"\")\n if api_key:\n return api_key\n else:\n raise ValueError(f\"环境变量 '{key_name}' 未设置,组件: {component_name}\")\n else:\n raise ValueError(f\"组件 '{component_name}' 未在 llmMappings 中配置\")\n except Exception as e:\n raise ValueError(f\"读取密钥配置失败: {e}\")\n raise ValueError(f\"无法获取组件 '{component_name}' 的 API 密钥\")\n\ndef run_node(node):\n Outputs.clear()\n for i in range(len(node['Outputs'])):\n Outputs.append(node['Outputs'][i])\n \n messages = node[\"messages\"]\n print('Test 1', messages)\n\n # Initialize the OpenAI client with DeepSeek API\n api_key = get_llm_api_key()\n client = OpenAI(api_key=api_key, base_url=\"https://api.deepseek.com\")\n if node['max_tokens'] >8192:\n node['max_tokens'] = 8192\n\n # Make the API call\n response = client.chat.completions.create(\n model=\"deepseek-reasoner\",\n messages=messages,\n temperature=node['temperature'],\n max_tokens=node['max_tokens'],\n top_p=node['Top_p'],\n frequency_penalty=node['frequency_penalty'],\n presence_penalty=node['presence_penalty'],\n stream=False\n )\n\n # Extract the response content\n Temp = response.choices[0].message.content\n\n def process_input_str(input_str):\n try:\n parsed_json = json.loads(input_str)\n return json.dumps(parsed_json, indent=4, ensure_ascii=False)\n except json.JSONDecodeError as e:\n return f\"Invalid JSON string. Error: {str(e)}\\nOriginal string: {input_str}\"\n\n def ensure_wrapped_with_braces(input_str):\n if input_str.startswith('```json') and input_str.endswith('```'):\n input_str = input_str[7:-3] # Remove ```json and ```\n\n input_str = clean_input_string(input_str)\n first_brace_pos = input_str.find('{')\n corresponding_closing_brace_pos = -1\n open_brace_count = 0\n\n if first_brace_pos == -1:\n return f'{{{input_str}}}'\n\n for i in range(first_brace_pos, len(input_str)):\n if input_str[i] == '{':\n open_brace_count += 1\n elif input_str[i] == '}':\n open_brace_count -= 1\n if open_brace_count == 0:\n corresponding_closing_brace_pos = i\n break\n\n input_str = input_str[first_brace_pos:corresponding_closing_brace_pos + 1]\n return process_input_str(input_str)\n\n def clean_input_string(input_string):\n quotes = re.findall(r'\"', input_string)\n if len(quotes) % 2 != 0:\n raise ValueError(\"Mismatched quotes\")\n\n cleaned_string = re.sub(r'\\(.*?\\)', '', input_string)\n cleaned_string = re.sub(r'[\\x00-\\x1F\\x7F]', '', cleaned_string)\n return cleaned_string\n\n print('Test 1 Temp', Temp)\n if node['OriginalTextSelector'] == 'Json':\n Temp_dict = json.loads(ensure_wrapped_with_braces(Temp))\n print('Test 2', Temp_dict)\n \n index = -1\n try:\n if node['OriginalTextSelector'] == 'Json':\n for key, value in Temp_dict.items():\n index += 1\n if Outputs[index]['Kind'] == 'String':\n Outputs[index]['Context'] = value\n elif Outputs[index]['Kind'] == 'Num':\n Outputs[index]['Num'] = int(value)\n elif Outputs[index]['Kind'] == 'Boolean':\n Outputs[index]['Boolean'] = value\n else:\n Outputs[0]['Context'] = Temp\n Outputs[0]['prompt_tokens'] = response.usage.prompt_tokens\n Outputs[0]['completion_tokens'] = response.usage.completion_tokens\n Outputs[0]['total_tokens'] = response.usage.total_tokens\n except Exception as e:\n raise Exception(f\"An error occurred: {e}. Temp_dict: {Temp_dict}\")\n\n return Outputs"}, "9e0345bdb1b7888d9750cf63ed5d93cb0b7aa43a": {"t": 1785764925.5955644, "n": 6399, "h": "95278d666182a368", "c": "import json\nimport re\nimport http.client\nimport base64\nfrom openai import OpenAI\nimport os\nfrom pathlib import Path\n#**Define the number of outputs and inputs\nOutPutNum = 1\nInPutNum = 0\n#**Define the number of outputs and inputs\nFunctionIntroduction='组件功能(简述代码整体功能)\\\\n这是一个基于 DeepSeek API 的大语言模型节点,支持文本和图像输入的多模态对话功能。该组件可以处理用户的文本提示和图像文件,通过 DeepSeek Reasoner 模型生成智能回复。\\\\n\\\\n代码功能摘要(概括核心算法或主要处理步骤)\\\\n核心功能包括图像文件的 Base64 编码转换、多模态消息构建、DeepSeek API 调用、响应内容的 JSON 格式化处理,以及输出结果的结构化封装。支持原始文本和 JSON 两种输出格式。\\\\n\\\\n参数\\\\n```yaml\\\\ninputs: []\\\\noutputs:\\\\n - name: OutPut1\\\\n type: string\\\\n description: 模型生成的回复内容\\\\n```\\\\n\\\\n运行逻辑\\\\n- 清空并重新初始化输出数组\\\\n- 遍历输入节点,检测文件路径类型的输入\\\\n- 将图像文件转换为 Base64 编码格式\\\\n- 根据原始文本选择器处理导出提示词\\\\n- 构建包含文本和图像的多模态消息数组\\\\n- 使用 DeepSeek API 密钥初始化 OpenAI 客户端\\\\n- 限制最大令牌数不超过 8192\\\\n- 调用 deepseek-reasoner 模型进行对话生成\\\\n- 提取 API 响应中的内容文本\\\\n- 根据输出格式选择器处理响应内容\\\\n- 如果选择 JSON 格式,则解析并格式化 JSON 数据\\\\n- 将处理后的结果分配给相应的输出节点\\\\n- 记录 API 调用的令牌使用统计信息\\\\n- 返回包含生成内容和统计信息的输出数组'\n\n#**Initialize Outputs and Inputs arrays and assign names directly\nOutputs = [{'Num': None, 'Kind': None,'Boolean':False, 'Id': f'Output{i + 1}', 'Context': None,'name':f'OutPut{i + 1}','Link':0,'Description':'answer'} for i in range(OutPutNum)]\nInputs = [{'Num': None, 'Kind': None, 'Id': f'Input{i + 1}', 'Context': None, 'Isnecessary': True,'name':f'Input{i + 1}','Link':0,'IsLabel':False} for i in range(InPutNum)]\n#**Initialize Outputs and Inputs arrays and assign names directly\nNodeKind = 'LLm'\nLable = [{'Id': 'Label1', 'Kind': 'None'}]\n\n#**Assign properties to Inputs\n\nfor output in Outputs:\n output['Kind'] = 'String'\n\nfor input in Inputs:\n input['Kind'] = 'String'\n#**Assign properties to Inputs\n\ndef image_to_base64(image_path):\n with open(image_path, \"rb\") as image_file:\n encoded_image = base64.b64encode(image_file.read())\n return encoded_image.decode('utf-8')\n\ndef get_llm_api_key():\n \"\"\"从环境变量读取当前组件的 API 密钥\"\"\"\n component_name = Path(__file__).stem\n try:\n edit_path = Path(__file__).parent.parent / \"Edit\" / \"Edit.json\"\n if edit_path.exists():\n with open(edit_path, 'r', encoding='utf-8') as f:\n config = json.load(f)\n llm_mappings = config.get('llmMappings', {})\n key_name = None\n for k, v in llm_mappings.items():\n if k.lower() == component_name.lower():\n key_name = v\n break\n if key_name:\n api_key = os.getenv(key_name, \"\")\n if api_key:\n return api_key\n else:\n raise ValueError(f\"环境变量 '{key_name}' 未设置,组件: {component_name}\")\n else:\n raise ValueError(f\"组件 '{component_name}' 未在 llmMappings 中配置\")\n except Exception as e:\n raise ValueError(f\"读取密钥配置失败: {e}\")\n raise ValueError(f\"无法获取组件 '{component_name}' 的 API 密钥\")\n\ndef run_node(node):\n Outputs.clear()\n for i in range(len(node['Outputs'])):\n Outputs.append(node['Outputs'][i])\n \n messages = node[\"messages\"]\n print('Test 1', messages)\n\n # Initialize the OpenAI client with DeepSeek API\n api_key = get_llm_api_key()\n client = OpenAI(api_key=api_key, base_url=\"https://api.deepseek.com\")\n if node['max_tokens'] >8192:\n node['max_tokens'] = 8192\n\n # Make the API call\n response = client.chat.completions.create(\n model=\"deepseek-reasoner\",\n messages=messages,\n temperature=node['temperature'],\n max_tokens=node['max_tokens'],\n top_p=node['Top_p'],\n frequency_penalty=node['frequency_penalty'],\n presence_penalty=node['presence_penalty'],\n stream=False\n )\n\n # Extract the response content\n Temp = response.choices[0].message.content\n\n def process_input_str(input_str):\n try:\n parsed_json = json.loads(input_str)\n return json.dumps(parsed_json, indent=4, ensure_ascii=False)\n except json.JSONDecodeError as e:\n return f\"Invalid JSON string. Error: {str(e)}\\nOriginal string: {input_str}\"\n\n def ensure_wrapped_with_braces(input_str):\n if input_str.startswith('```json') and input_str.endswith('```'):\n input_str = input_str[7:-3] # Remove ```json and ```\n\n input_str = clean_input_string(input_str)\n first_brace_pos = input_str.find('{')\n corresponding_closing_brace_pos = -1\n open_brace_count = 0\n\n if first_brace_pos == -1:\n return f'{{{input_str}}}'\n\n for i in range(first_brace_pos, len(input_str)):\n if input_str[i] == '{':\n open_brace_count += 1\n elif input_str[i] == '}':\n open_brace_count -= 1\n if open_brace_count == 0:\n corresponding_closing_brace_pos = i\n break\n\n input_str = input_str[first_brace_pos:corresponding_closing_brace_pos + 1]\n return process_input_str(input_str)\n\n def clean_input_string(input_string):\n quotes = re.findall(r'\"', input_string)\n if len(quotes) % 2 != 0:\n raise ValueError(\"Mismatched quotes\")\n\n cleaned_string = re.sub(r'\\(.*?\\)', '', input_string)\n cleaned_string = re.sub(r'[\\x00-\\x1F\\x7F]', '', cleaned_string)\n return cleaned_string\n\n print('Test 1 Temp', Temp)\n if node['OriginalTextSelector'] == 'Json':\n Temp_dict = json.loads(ensure_wrapped_with_braces(Temp))\n print('Test 2', Temp_dict)\n \n index = -1\n try:\n if node['OriginalTextSelector'] == 'Json':\n for key, value in Temp_dict.items():\n index += 1\n if Outputs[index]['Kind'] == 'String':\n Outputs[index]['Context'] = value\n elif Outputs[index]['Kind'] == 'Num':\n Outputs[index]['Num'] = int(value)\n elif Outputs[index]['Kind'] == 'Boolean':\n Outputs[index]['Boolean'] = value\n else:\n Outputs[0]['Context'] = Temp\n Outputs[0]['prompt_tokens'] = response.usage.prompt_tokens\n Outputs[0]['completion_tokens'] = response.usage.completion_tokens\n Outputs[0]['total_tokens'] = response.usage.total_tokens\n except Exception as e:\n raise Exception(f\"An error occurred: {e}. Temp_dict: {Temp_dict}\")\n\n return Outputs"}}}} |