add aimage

This commit is contained in:
lychang
2025-09-28 15:42:56 +08:00
parent 19e2c0281e
commit 69dc4b759c
9 changed files with 365 additions and 62779 deletions

View File

@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="com.codeverse.userSettings.MarscodeWorkspaceAppSettingsState">
<option name="chatAppRouterInfo" value="builder/68c8f7450a2cf159804a74cc" />
<option name="chatAppRouterInfo" value="builder/68d8bbf974c6ec0536baf3c2" />
<option name="progress" value="1.0" />
</component>
</project>

2
.idea/misc.xml generated
View File

@@ -3,5 +3,5 @@
<component name="Black">
<option name="sdkName" value="Python 3.11 (image_recognition)" />
</component>
<component name="ProjectRootManager" version="2" project-jdk-name="Python 3.10 (wxwork)" project-jdk-type="Python SDK" />
<component name="ProjectRootManager" version="2" project-jdk-name="Python 3.9 (scf)" project-jdk-type="Python SDK" />
</project>

View File

@@ -4,7 +4,7 @@
<content url="file://$MODULE_DIR$">
<excludeFolder url="file://$MODULE_DIR$/.idea/dataSources" />
</content>
<orderEntry type="jdk" jdkName="Python 3.10 (wxwork)" jdkType="Python SDK" />
<orderEntry type="jdk" jdkName="Python 3.9 (scf)" jdkType="Python SDK" />
<orderEntry type="sourceFolder" forTests="false" />
</component>
<component name="PyDocumentationSettings">

107
aimage.py Normal file
View File

@@ -0,0 +1,107 @@
import requests
from jimeng import VolcEngineAPIClient
def post_request(url, data, headers=None):
if headers is None:
resp = requests.post(url, json=data)
else:
resp = requests.post(url, json=data, headers=headers)
return resp.json()
def chat_deepseek(message, role):
url = "https://api.deepseek.com/chat/completions"
headers = {
"Content-Type": "application/json",
"Authorization": "Bearer sk-c2f04b4d635b4df0aace0432f3c6d6f4"
}
body = {
"model": "deepseek-chat",
"messages": [
{"role": "system", "content": role},
{"role": "user", "content": message}
],
"stream": False
}
result = post_request(url, body, headers)
if "choices" in result:
return result['choices'][0]['message']['content']
return ""
def get_image_prompt(message):
role = """你是世界一流的AI生图提示词撰写大师, 你精通心理学、人工智能、工业设计/平面设计、传播学、市场学、哲学、美学,你需要根据用户的需求撰写面向豆包/即梦文生图4.0模型的AI生图提示词。
## 遵循框架
1. 核心风格
这是作品的灵魂,决定了整体的视觉基调。
主导风格: 必须明确指定。例如:写实主义、印象派、赛博朋克、浮世绘、极简主义、超现实主义、儿童插画、蒸汽波、水墨风、概念艺术等。
艺术家或作品参考: 可以具体到某位艺术家的风格(如“梵高的笔触与色彩”、“穆夏的装饰性线条”)或某部著名作品的风格。
技术质感: 描述画作的物理质感。例如:油画厚重的笔触、水彩的晕染感、版画的刻痕、数字绘画的光滑、铅笔素描的颗粒感。
2. 主题与场景
这是作品的叙事发生地,构建了基本语境。
核心主题: 用一句话概括画作讲述的故事或表达的核心概念(如:“孤独的宇航员在异星探险”)。
具体场景: 详细描述环境。例如:繁华的未来都市街角、静谧的森林深处、暴风雨中的海岸、充满温馨灯光的室内书房。
氛围与情感: 定义画面传递的情绪。例如:神秘、宁静、悲壮、欢快、压抑、充满希望。(关键补充) 此部分应指导色彩和构图的选择。
3. 主体内容
这是画面的视觉焦点,最吸引观众视线的部分。
主体对象: 详细描述核心人物、物体或文字。
形态与姿态: 如果是人物或生物,描述其动作、表情、服装细节。
材质与质感: 描述物体的表面特性(如:金属的反光、毛绒的柔软、石头的粗糙、玻璃的透明)。
视角与焦点: 描述观看主体的角度(如:仰视以显雄伟、俯视以显渺小、特写以显细节)。景深是清晰还是模糊。
(关键补充)视觉权重: 说明主体在画面中的大小和位置,以确保其核心地位。
4. 背景与构图
这是支撑主体、深化主题的舞台,决定了画面的空间感和结构。
构图法则: 明确采用的构图方式。例如:三分法、对称式、对角线式、中心式、框架式构图。
背景内容: 描述主体之后的所有元素。例如:远山、云彩、建筑、人群、抽象的光影或色块。背景应与主题和氛围一致。
空间层次: 明确前景、中景、背景的区分,以创造纵深感。例如:前景是几支模糊的芦苇(前景),中景是小船和人物(主体),背景是朦胧的山脉(背景)。
视觉引导: 画面中的线条、光影或色彩如何自然地引导观众的视线走向主体。
5. 色彩与光影
这是渲染氛围、表达情感的关键工具。
色彩基调: 定义主色调和配色方案。例如:暖色调(温馨)、冷色调(清冷)、互补色(强烈)、类比色(和谐)、单色调(高级)。
光影设计:
光源: 描述光的方向(侧光、顶光、逆光)、类型(自然光、烛光、霓虹光)和强度(强烈对比的硬光、柔和的漫射光)。
阴影: 阴影的形状、硬度和透明度,对塑造形体至关重要。
6. 标题与文字集成(如适用)
如果画作包含文字,需进行一体化设计。
文字内容: 明确主标题、副标题或说明文字的具体文案。
字体风格: 选择与绘画风格匹配的字体。例如:衬线体(古典、正式)、无衬线体(现代、简洁)、书法体(优雅、艺术)、手写体(亲切、随意)。
排版与集成: 文字在画面中的位置(顶部、底部、融入背景等)、颜色、大小和透明度,确保它与图像和谐共存,而非生硬粘贴。
7. 整体优化建议(新增项)
一致性检查: 确保风格、场景、色彩、光影等所有元素共同服务于同一个主题和情感。
独特点: 思考画面中最具创新性或最吸引人的“记忆点”是什么。
最终效果: 期望观众看到这幅画时产生怎样的感受或思考。
## 工作流程:
1.分析我给的绘画主题。
2.按照内容要求写出完整详细的绘画设计文本字数不超过500字
3.按照内容要求逐项填写绘画设计文本
"""
message = f"我的绘画主题是:{message}"
prompt = chat_deepseek(message, role)
return prompt
if __name__ == '__main__':
prompt = get_image_prompt("""
使用赛博科技的绘画风格
信息披露成绩单
沪深两所上市公司信息披露考评
新 和 成
连续 16 年荣获信披考评 A
2023~2024 年度参与信披评价考核的上市公司共5054家
本年度被评为 A(优秀)的上市公司共 911 家,占比 18.03%
连续 8 年及以上被评为 A(优秀)的上市公司共 127 家,占比 2.51%
胜人者有力
自胜者自强""")
print(prompt)
veac = VolcEngineAPIClient('AKLTZjg1MGViN2E4ODU1NGY4MzlmYTg2ODRjMzBlYmQ4NTk',
'WlRoak1qZzJPR1EzTm1JeU5EQmhOamswWWpSa09UbGhNek5pT0RkbE1tRQ==')
result = veac.run(prompt,"url",try_times=1)
print(result)

View File

@@ -527,14 +527,3 @@ class ESmart:
if resp.status_code == 200:
return resp.json()
return {}
if __name__ == '__main__':
# esmart = ESmart()
# esmart.prepared_message()
sta = SmartTableApi("dcxzIyHG8nZDXswX00xaTDBGgW9NQ00Qk5WH6zLPTFONlE42y2CWZ8nCG8O-gvZSA5dRjTDASSThVAk2iWF16MAg")
sta.add_sheet("维护更新")
sta.add_sheet("VIP交付情况")
sta.add_sheet("备份存档")
# sta.create("推广-深交所用户智能跟踪",
# ["lychang", "rhu"])

View File

@@ -1,17 +1,21 @@
# !/usr/bin/env python
# -*- coding:utf-8 -*-
import base64
import re
import requests
from aimage import get_image_prompt
from jimeng import VolcEngineAPIClient
from router import Router, Response
from esmart import SmartTableApi, transform_data, SmartSheet, ESmart, push_message
from esmart import transform_data, SmartSheet, ESmart, push_message
from lib import parse_data, get_approval, generate_approval_report_html, new_product_print, SalesTools, CalendarEventDB
st = SalesTools()
ceb = CalendarEventDB()
esmart = ESmart()
router = Router()
vea = VolcEngineAPIClient('AKLTZjg1MGViN2E4ODU1NGY4MzlmYTg2ODRjMzBlYmQ4NTk',
'WlRoak1qZzJPR1EzTm1JeU5EQmhOamswWWpSa09UbGhNek5pT0RkbE1tRQ==')
def old_handle(request):
@@ -24,25 +28,6 @@ def old_handle(request):
address = data.get("address", "lychang@genesysinfo.net")
st.send_company_mail(address, "客户拜访审批次数报表", result)
return Response({"code": 200, "msg": "success", "update": "迁移到[GET](/approval/sales_call)路径访问"}, 304)
elif data.get("action") == "otp":
push_message("otp数据迁移", f"有人正在使用[action:otp]接口", "")
data_list = data.get("data", [{}])
sta = SmartTableApi(
"dcqzSDHPl2ZWoLkEB3Id1wMMaW0meMSwGLjfnuHD0VMh0DVidKdal-3wYfsh7Zb1pGn9moDuzjvhtlRZAXoO-Hjg")
mapping = {
"userName": "用户名称",
"secCode": "公司代码",
"companyName": "公司名称",
"count": "使用动态口令次数",
"date": "时间",
"goodName": "产品"
}
data_list = [transform_data(i, mapping) for i in data_list]
cursor = sta.get_sheet("g6dTI2")
if cursor.batch_add(data_list):
return Response({"code": 200, "msg": "success", "update": "迁移到[POST](/otp)路径访问"}, 304)
else:
return Response({"code": 500, "msg": "error", "update": "迁移到[POST](/otp)路径访问"}, 304)
elif template_id == "C4ZT8ZuPRbKC76KmWCrmRAKyVdneoq9wh1ESaUrrJ":
push_message("approval接口迁移", f"有人正在使用[approval:C4ZT8ZuPRbKC76KmWCrmRAKyVdneoq9wh1ESaUrrJ]接口", "")
info = parse_data(data, {"Number-1697103952657": "company_code", "Text-1697103919621": "company_name",
@@ -226,5 +211,37 @@ def esmart_security_mapping(request):
return Response(esmart.security_mapping)
@router.route('/image/generate', methods=['POST'])
def image_generate(request):
"""绘制相关图像"""
prompt = request.body.get('prompt', "")
source = request.body.get('source', "url")
if prompt:
prompt = get_image_prompt(prompt)
result = vea.run(prompt, source, 1)
if source != "url":
result = str(base64.b64encode(result))[2:-1]
return Response(result)
else:
return Response({
'success': False,
'message': f'prompt 不能为空'
}, 400)
@router.route('/image/prompt', methods=['POST'])
def image_prompt(request):
"""获取绘制图像详细提示词"""
prompt = request.body.get('prompt', "")
if prompt:
prompt = get_image_prompt(prompt)
return Response(prompt)
else:
return Response({
'success': False,
'message': f'prompt 不能为空'
}, 400)
def main_handler(event, context):
return router.handle_request(event)

217
jimeng.py Normal file
View File

@@ -0,0 +1,217 @@
import json
import sys
import os
import base64
import datetime
import hashlib
import hmac
import time
import requests
class VolcEngineAPIClient:
"""火山引擎API客户端类"""
def __init__(self, access_key: str, secret_key: str, service: str = 'cv',
region: str = 'cn-north-1', endpoint: str = 'https://visual.volcengineapi.com'):
"""
初始化API客户端
Args:
access_key: 访问密钥
secret_key: 秘密密钥
service: 服务名称,默认为'cv'
region: 区域,默认为'cn-north-1'
endpoint: API端点默认为'https://visual.volcengineapi.com'
"""
self.access_key = access_key
self.secret_key = secret_key
self.service = service
self.region = region
self.endpoint = endpoint
self.host = 'visual.volcengineapi.com'
self.method = 'POST'
@staticmethod
def _sign(key, msg: str) -> bytes:
"""HMAC签名方法"""
return hmac.new(key, msg.encode('utf-8'), hashlib.sha256).digest()
def _get_signature_key(self, key: str, date_stamp: str, region_name: str, service_name: str) -> bytes:
"""生成签名密钥"""
k_date = self._sign(key.encode('utf-8'), date_stamp)
k_region = self._sign(k_date, region_name)
k_service = self._sign(k_region, service_name)
k_signing = self._sign(k_service, 'request')
return k_signing
@staticmethod
def _format_query(parameters: dict) -> str:
"""格式化查询参数"""
request_parameters_init = ''
for key in sorted(parameters):
request_parameters_init += key + '=' + parameters[key] + '&'
request_parameters = request_parameters_init[:-1]
return request_parameters
def _generate_signature_v4(self, req_query: str, req_body: str):
"""生成V4签名"""
if self.access_key is None or self.secret_key is None:
raise ValueError('No access key is available.')
t = datetime.datetime.utcnow()
current_date = t.strftime('%Y%m%dT%H%M%SZ')
datestamp = t.strftime('%Y%m%d') # Date w/o time, used in credential scope
canonical_uri = '/'
canonical_querystring = req_query
signed_headers = 'content-type;host;x-content-sha256;x-date'
payload_hash = hashlib.sha256(req_body.encode('utf-8')).hexdigest()
content_type = 'application/json'
canonical_headers = 'content-type:' + content_type + '\n' + 'host:' + self.host + \
'\n' + 'x-content-sha256:' + payload_hash + \
'\n' + 'x-date:' + current_date + '\n'
canonical_request = self.method + '\n' + canonical_uri + '\n' + canonical_querystring + \
'\n' + canonical_headers + '\n' + signed_headers + '\n' + payload_hash
algorithm = 'HMAC-SHA256'
credential_scope = datestamp + '/' + self.region + '/' + self.service + '/' + 'request'
string_to_sign = algorithm + '\n' + current_date + '\n' + credential_scope + '\n' + hashlib.sha256(
canonical_request.encode('utf-8')).hexdigest()
signing_key = self._get_signature_key(self.secret_key, datestamp, self.region, self.service)
signature = hmac.new(signing_key, string_to_sign.encode('utf-8'), hashlib.sha256).hexdigest()
authorization_header = algorithm + ' ' + 'Credential=' + self.access_key + '/' + \
credential_scope + ', ' + 'SignedHeaders=' + \
signed_headers + ', ' + 'Signature=' + signature
headers = {
'X-Date': current_date,
'Authorization': authorization_header,
'X-Content-Sha256': payload_hash,
'Content-Type': content_type
}
return headers, current_date
def send_request(self, query_params: dict, body_params: dict) -> dict:
"""
发送API请求
Args:
query_params: 查询参数
body_params: 请求体参数
Returns:
dict: 响应对象
"""
formatted_query = self._format_query(query_params)
formatted_body = json.dumps(body_params)
headers, current_date = self._generate_signature_v4(formatted_query, formatted_body)
request_url = self.endpoint + '?' + formatted_query
try:
response = requests.post(request_url, headers=headers, data=formatted_body)
if response.status_code != 200:
raise Exception(f'HTTP error! status: {response.status_code}, response: {response.text}')
return response.json()
except Exception as err:
print(f'error occurred: {err}')
raise
def cv_process(self, req_key: str, **kwargs) -> dict:
"""
CV处理接口
Args:
req_key: 请求键
**kwargs: 其他参数
Returns:
dict: 响应对象
"""
query_params = {
'Action': 'CVSync2AsyncSubmitTask',
'Version': '2022-08-31',
}
body_params = {
"req_key": req_key,
**kwargs
}
return self.send_request(query_params, body_params)["data"]
def get_image_url(self, req_key, task_id: str) -> dict:
query_params = {
'Action': 'CVSync2AsyncGetResult',
'Version': '2022-08-31',
}
req_json = {"return_url": True}
body_params = {
"req_key": req_key,
"task_id": task_id,
"req_json": json.dumps(req_json, ensure_ascii=False),
}
return self.send_request(query_params, body_params)
def get_image(self, req_key, task_id: str) -> bytes:
image_info = self.get_image_url(req_key, task_id)
image_urls = image_info["data"]["image_urls"]
if image_urls:
image_url = image_urls[0]
response = requests.get(image_url)
return response.content
else:
return b""
def _run(self, prompt: str, blocking_times: int = 5, wait_time: int = 5,model: str = "jimeng_t2i_v31"):
try:
task_info = self.cv_process(model,
prompt=prompt,
seed=-1,
width=936,
height=1664,
use_pre_llm=False
)
task_id = task_info["task_id"]
for i in range(blocking_times):
time.sleep(wait_time)
image_info = self.get_image_url(model, task_id)
image_urls = image_info["data"]["image_urls"]
if image_urls:
image_url = image_urls[0]
return image_url
else:
print("生成时间过长")
return ""
except Exception as e:
print(f"请求失败: {e}")
return ""
def run(self, prompt: str,return_type: str = "content", try_times: int = 2):
for _ in range(try_times):
url = self._run(prompt,model="jimeng_t2i_v31")
if url:
if return_type == "content":
resp = requests.get(url)
if resp.status_code != 200:
raise Exception(f'HTTP error! status: {resp.status_code}, response: {resp.text}')
return resp.content
else:
return url
else:
print("生成失败")
return None

1
lib.py
View File

@@ -1116,7 +1116,6 @@ class CalendarEventDB(CalendarDB):
content = f.read()
content = content.replace("{{report_ticket}}", report_ticket)
content = content.replace("{{regression_testing}}", regression_testing)
# content = content.replace("{{qrcode}}", qrcode)
content = content.replace("{{picture}}", st.get_information_disclosure_picture("2024", security_code))
st.send_company_mail(bp_mail, f"客户拜访准备文件-{full_name}[{security_code}]", content)
ssp.add_row(doc_id=f_id, sheet_id="tTMuVB", records=[

62743
package.json

File diff suppressed because it is too large Load Diff