Initial commit: AI tagging images project

This commit is contained in:
2026-01-30 18:30:05 +08:00
commit 2882852cd2
20 changed files with 3310 additions and 0 deletions

View File

@@ -0,0 +1,261 @@
# -*- coding: utf-8 -*-
"""
千问大模型 - 图片标签衍生生成器
从 ai_image_tags 表获取图片和标签,调用千问大模型生成标签衍生
配置统一从 config/settings.py 读取
"""
import os
import sys
import json
from http import HTTPStatus
# 添加项目根目录到路径
sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
# 导入统一配置
from config.settings import settings
from database_config import get_image_tags_dao, ImageTagsDAO
# 尝试导入dashscope如果没有安装会提示
try:
import dashscope
from dashscope import MultiModalConversation
except ImportError:
print("请先安装 dashscope: pip install dashscope")
exit(1)
# ============== 提示词模板 ==============
TAG_DERIVE_PROMPT_TEMPLATE = """你是一个专业的医疗健康内容标签分析专家。
## 任务
请根据提供的图片和当前标签,生成相关的衍生标签。
## 当前标签
{tag_name}
## 要求
1. 根据图片内容和当前标签,生成 5-10 个相关的衍生标签
2. 衍生标签应该包括:
- 同义词/近义词标签
- 上位概念标签(更宽泛的分类)
- 下位概念标签(更具体的细分)
- 相关联想标签(与主题相关但角度不同)
- 应用场景标签(使用场景或人群)
3. 标签要简洁每个标签不超过10个字
4. 标签要与医疗健康领域相关
## 输出格式
请以JSON格式输出包含以下字段
```json
{{
"original_tag": "原始标签",
"derived_tags": [
{{"tag": "衍生标签1", "type": "同义词", "relevance": ""}},
{{"tag": "衍生标签2", "type": "上位概念", "relevance": ""}},
...
],
"tag_description": "对原始标签的简要描述",
"suggested_keywords": ["关键词1", "关键词2", ...]
}}
```
"""
# 纯文本模式的提示词(不使用图片)
TAG_DERIVE_TEXT_PROMPT_TEMPLATE = """你是一个专业的医疗健康内容标签分析专家。
## 任务
请根据提供的标签,生成相关的衍生标签。
## 当前标签
{tag_name}
## 图片信息
图片名称:{image_name}
## 要求
1. 根据当前标签,生成 5-10 个相关的衍生标签
2. 衍生标签应该包括:
- 同义词/近义词标签
- 上位概念标签(更宽泛的分类)
- 下位概念标签(更具体的细分)
- 相关联想标签(与主题相关但角度不同)
- 应用场景标签(使用场景或人群)
3. 标签要简洁每个标签不超过10个字
4. 标签要与医疗健康领域相关
## 输出格式
请以JSON格式输出包含以下字段
```json
{{
"original_tag": "原始标签",
"derived_tags": [
{{"tag": "衍生标签1", "type": "同义词", "relevance": ""}},
{{"tag": "衍生标签2", "type": "上位概念", "relevance": ""}},
...
],
"tag_description": "对原始标签的简要描述",
"suggested_keywords": ["关键词1", "关键词2", ...]
}}
```
"""
class QwenTagDeriver:
"""千问标签衍生生成器"""
def __init__(self, api_key: str = None):
self.api_key = api_key or settings.qwen.api_key
dashscope.api_key = self.api_key
self.dao = get_image_tags_dao() # 使用统一的数据库配置
def get_image_tags_from_db(self, limit: int = 10, offset: int = 0) -> list:
"""从数据库获取图片标签数据"""
return self.dao.get_for_tag_derive(limit=limit, offset=offset)
def generate_prompt(self, tag_name: str, image_name: str = "", use_image: bool = False) -> str:
"""生成提示词"""
if use_image:
return TAG_DERIVE_PROMPT_TEMPLATE.format(tag_name=tag_name)
else:
return TAG_DERIVE_TEXT_PROMPT_TEMPLATE.format(
tag_name=tag_name,
image_name=image_name
)
def call_qwen_with_image(self, image_url: str, tag_name: str) -> dict:
"""调用千问多模态模型(带图片)"""
prompt = self.generate_prompt(tag_name, use_image=True)
messages = [
{
"role": "user",
"content": [
{"image": image_url},
{"text": prompt}
]
}
]
response = MultiModalConversation.call(
model=settings.qwen.vision_model, # 千问视觉大模型
messages=messages
)
if response.status_code == HTTPStatus.OK:
return {
"success": True,
"result": response.output.choices[0].message.content[0]["text"]
}
else:
return {
"success": False,
"error": f"Error: {response.code} - {response.message}"
}
def call_qwen_text_only(self, tag_name: str, image_name: str = "") -> dict:
"""调用千问文本模型(不带图片)"""
from dashscope import Generation
prompt = self.generate_prompt(tag_name, image_name, use_image=False)
response = Generation.call(
model=settings.qwen.text_model, # 使用配置中的文本模型
prompt=prompt,
result_format="message"
)
if response.status_code == HTTPStatus.OK:
return {
"success": True,
"result": response.output.choices[0].message.content
}
else:
return {
"success": False,
"error": f"Error: {response.code} - {response.message}"
}
def derive_tags_for_image(self, image_data: dict, use_image: bool = False) -> dict:
"""为单个图片生成衍生标签"""
tag_name = image_data.get("tag_name", "")
image_url = image_data.get("image_url", "")
image_name = image_data.get("image_name", "")
print(f"\n处理标签: {tag_name}")
print(f"图片URL: {image_url[:50]}..." if len(image_url) > 50 else f"图片URL: {image_url}")
if use_image and image_url:
result = self.call_qwen_with_image(image_url, tag_name)
else:
result = self.call_qwen_text_only(tag_name, image_name)
return {
"image_id": image_data.get("image_id"),
"tag_id": image_data.get("tag_id"),
"original_tag": tag_name,
"image_url": image_url,
"derive_result": result
}
def batch_derive_tags(self, limit: int = 5, use_image: bool = False) -> list:
"""批量生成衍生标签"""
image_tags = self.get_image_tags_from_db(limit=limit)
results = []
for item in image_tags:
result = self.derive_tags_for_image(item, use_image)
results.append(result)
return results
def main():
"""主函数 - 演示用法"""
print("=" * 60)
print("千问大模型 - 图片标签衍生生成器")
print("=" * 60)
# 初始化
deriver = QwenTagDeriver()
# 1. 从数据库获取数据示例
print("\n[1] 从数据库获取图片标签数据...")
try:
image_tags = deriver.get_image_tags_from_db(limit=3)
if image_tags:
print(f"获取到 {len(image_tags)} 条数据:")
for item in image_tags:
print(f" - ID: {item['id']}, 标签: {item['tag_name']}")
else:
print("数据库中暂无数据")
except Exception as e:
print(f"数据库连接失败: {e}")
image_tags = []
# 2. 生成提示词示例
print("\n[2] 生成提示词示例:")
sample_tag = "高血压"
sample_prompt = deriver.generate_prompt(sample_tag, "blood_pressure.jpg")
print("-" * 40)
print(sample_prompt[:500] + "..." if len(sample_prompt) > 500 else sample_prompt)
print("-" * 40)
# 3. 调用千问API需要有效的API Key
print("\n[3] 调用千问API生成衍生标签...")
if not settings.qwen.api_key or settings.qwen.api_key == "your-api-key-here":
print("请先设置有效的 DASHSCOPE_API_KEY")
print("可以通过环境变量设置: export DASHSCOPE_API_KEY=your-key")
print("或修改 config/settings.py 中的配置")
else:
# 使用文本模式调用
result = deriver.call_qwen_text_only(sample_tag, "示例图片")
if result["success"]:
print("生成结果:")
print(result["result"])
else:
print(f"调用失败: {result['error']}")
if __name__ == "__main__":
main()