共绩科技
共绩科技

预制服务

容器化部署 Qwen3-8B-VL

此镜像提供了标准化的 API 接口 ,让您能够便捷地通过 API 调用方式 访问和使用所有功能。

此镜像提供了标准化的 API 接口,让您能够便捷地通过 API 调用方式访问和使用所有功能。

目前还不支持 Web UI 方式使用服务,需要您本地启动适配的 Web UI。

API 配置信息

在使用以下代码前,请先了解 API 配置信息:

  • API 端点: https://deployment-318-nmu4u9xb-8000.550w.link
  • 模型名称: Qwen/Qwen3-VL-8B-Instruct-FP8
  • 上下文长度: 32K
  • 推荐参数配置:
  • 温度 (temperature): 0.6
  • Top-K: 20Q
  • Top-P: 0.95
  • 最大 token 数 (max_tokens): 2048

完整代码实现

#!/usr/bin/env python3
"""
Qwen3-VL API 综合测试脚本
包含所有功能的测试示例
"""

import os
import json
import base64
import requests
from typing import List, Dict, Optional, Union
from PIL import Image
import io

class Qwen3VLClient:
    """Qwen3-VL API 客户端类"""
    """str 中直接复制预制镜像中 8000 端口的链接过来即可"""
    def __init__(self, base_url: str = "https://deployment-318-nmu4u9xb-8000.550w.link"):
        """
        初始化客户端

        Args:
            base_url: API 基础 URL
        """
        self.base_url = base_url.rstrip('/')
        self.chat_endpoint = f"{self.base_url}/v1/chat/completions"
        self.session = requests.Session()
        self.session.headers.update({
            "Content-Type": "application/json",
            "Accept": "application/json"
        })

    def _encode_image(self, image_path: str) -> str:
        """
        将图像文件编码为 base64 字符串

        Args:
            image_path: 图像文件路径

        Returns:
            base64 编码的图像字符串
        """
        try:
            with open(image_path, "rb") as image_file:
                return base64.b64encode(image_file.read()).decode('utf-8')
        except Exception as e:
            raise ValueError(f"无法编码图像 {image_path}: {str(e)}")

    def _prepare_messages(self,
                          text: str,
                          images: Optional[List[str]] = None,
                          conversation_history: Optional[List[Dict]] = None) -> List[Dict]:
        """
        准备 API 请求的消息格式

        Args:
            text: 文本消息
            images: 图像路径列表
            conversation_history: 对话历史

        Returns:
            格式化的消息列表
        """
        messages = []

        # 添加对话历史
        if conversation_history:
            messages.extend(conversation_history)

        # 准备当前消息内容
        content = [{"type": "text", "text": text}]

        # 添加图像
        if images:
            for img_path in images:
                if os.path.exists(img_path):
                    base64_image = self._encode_image(img_path)
                    content.append({
                        "type": "image_url",
                        "image_url": {
                            "url": f"data:image/jpeg;base64,{base64_image}"
                        }
                    })
                else:
                    print(f"警告:图像文件不存在:{img_path}")

        # 添加当前消息
        messages.append({"role": "user", "content": content})

        return messages

    def chat(self,
             text: str,
             images: Optional[List[str]] = None,
             conversation_history: Optional[List[Dict]] = None,
             model: str = "Qwen/Qwen3-VL-8B-Instruct-FP8",
             max_tokens: int = 2048,
             temperature: float = 0.7,
             top_k: int = 20,
             top_p: float = 0.8,
             stream: bool = False) -> Union[Dict, None]:
        """
        与模型进行对话

        Args:
            text: 输入文本
            images: 图像路径列表
            conversation_history: 对话历史
            model: 模型名称
            max_tokens: 最大生成 token 数
            temperature: 温度参数,控制随机性
            top_k: Top-K 采样参数
            top_p: Top-P 采样参数
            stream: 是否使用流式输出

        Returns:
            API 响应结果
        """
        messages = self._prepare_messages(text, images, conversation_history)

        payload = {
            "model": model,
            "messages": messages,
            "max_tokens": max_tokens,
            "temperature": temperature,
            "top_k": top_k,
            "top_p": top_p,
            "stream": stream
        }

        try:
            response = self.session.post(
                self.chat_endpoint,
                json=payload,
                timeout=60
            )
            response.raise_for_status()
            return response.json()
        except requests.exceptions.RequestException as e:
            print(f"API 请求错误:{str(e)}")
            return None

    def conversation_chat(self,
                         conversation_history: List[Dict],
                         new_message: str,
                         images: Optional[List[str]] = None,
                         model: str = "Qwen/Qwen3-VL-8B-Instruct-FP8",
                         max_tokens: int = 2048,
                         temperature: float = 0.7,
                         top_k: int = 20,
                         top_p: float = 0.8) -> Dict:
        """
        进行多轮对话

        Args:
            conversation_history: 对话历史
            new_message: 新消息
            images: 图像路径列表
            model: 模型名称
            max_tokens: 最大生成 token 数
            temperature: 温度参数
            top_k: Top-K 采样参数
            top_p: Top-P 采样参数

        Returns:
            包含回复和更新后对话历史的字典
        """
        response = self.chat(
            text=new_message,
            images=images,
            conversation_history=conversation_history,
            model=model,
            max_tokens=max_tokens,
            temperature=temperature,
            top_k=top_k,
            top_p=top_p
        )

        if response and "choices" in response and len(response["choices"]) > 0:
            reply = response["choices"][0]["message"]["content"]

            # 更新对话历史
            updated_history = conversation_history.copy()
            updated_history.append({"role": "user", "content": new_message})
            updated_history.append({"role": "assistant", "content": reply})

            return {
                "reply": reply,
                "updated_history": updated_history,
                "response": response
            }
        else:
            return {
                "reply": "抱歉,我无法处理您的请求。",
                "updated_history": conversation_history,
                "response": response
            }

class QwenVLDeveloper:
    """Qwen3-VL 开发者工具类,提供高级功能"""

    def __init__(self, base_url="https://deployment-318-nmu4u9xb-8000.550w.link"):
        """
        初始化开发者工具

        Args:
            base_url: API 基础 URL
        """
        self.client = Qwen3VLClient(base_url)
        self.conversation_history = []

    def chat_with_memory(self, text, images=None, temperature=0.7, top_k=20, top_p=0.8):
        """
        带记忆的对话功能

        Args:
            text: 输入文本
            images: 图像路径列表
            temperature: 温度参数
            top_k: Top-K 采样参数
            top_p: Top-P 采样参数

        Returns:
            模型回复
        """
        result = self.client.conversation_chat(
            conversation_history=self.conversation_history,
            new_message=text,
            images=images,
            temperature=temperature,
            top_k=top_k,
            top_p=top_p
        )
        self.conversation_history = result["updated_history"]
        return result["reply"]

    def analyze_document(self, image_path, analysis_type="comprehensive"):
        """
        文档图像分析

        Args:
            image_path: 文档图像路径
            analysis_type: 分析类型 (comprehensive, text_only, tables, formulas)

        Returns:
            分析结果
        """
        prompts = {
            "comprehensive": "请分析这个文档图像,提取其中的所有文本内容、表格数据和公式。请以结构化的方式呈现结果。",
            "text_only": "请提取这个文档图像中的所有文本内容,保持原有的格式和结构。",
            "tables": "请识别并提取这个文档图像中的所有表格数据,以 Markdown 表格格式呈现。",
            "formulas": "请识别并提取这个文档图像中的所有数学公式,以 LaTeX 格式呈现。"
        }

        prompt = prompts.get(analysis_type, prompts["comprehensive"])

        return self.client.chat(
            text=prompt,
            images=[image_path],
            temperature=0.3,  # 较低温度以提高准确性
            top_k=10,
            top_p=0.9
        )

    def generate_code_from_ui(self, ui_image_path, framework="html"):
        """
        从 UI 设计图生成代码

        Args:
            ui_image_path: UI 设计图像路径
            framework: 目标框架 (html, react, vue)

        Returns:
            生成的代码
        """
        framework_prompts = {
            "html": "请根据这个 UI 设计图生成完整的 HTML 代码,包括 CSS 样式。确保布局和视觉效果与设计图一致。",
            "react": "请根据这个 UI 设计图生成 React 组件代码,包括必要的样式和交互逻辑。",
            "vue": "请根据这个 UI 设计图生成 Vue 组件代码,包括模板、脚本和样式部分。"
        }

        prompt = framework_prompts.get(framework, framework_prompts["html"])

        return self.client.chat(
            text=prompt,
            images=[ui_image_path],
            temperature=0.2,  # 低温度以确保代码准确性
            top_k=5,
            top_p=0.95
        )

    def create_educational_content(self, image_path, content_type="explanation"):
        """
        从图像创建教育内容

        Args:
            image_path: 图像路径
            content_type: 内容类型 (explanation, quiz, tutorial)

        Returns:
            教育内容
        """
        prompts = {
            "explanation": "请详细解释这张图像中的概念,适合初学者理解。包括关键术语的定义和实际应用示例。",
            "quiz": "基于这张图像,创建 5 个不同难度的问题,用于测试学生对相关概念的理解。包括答案和解析。",
            "tutorial": "基于这张图像,创建一个分步教程,解释如何理解和应用其中的概念。"
        }

        prompt = prompts.get(content_type, prompts["explanation"])

        return self.client.chat(
            text=prompt,
            images=[image_path],
            temperature=0.6,
            top_k=15,
            top_p=0.85
        )

    def batch_analyze_images(self, image_paths, analysis_prompt):
        """
        批量分析图像

        Args:
            image_paths: 图像路径列表
            analysis_prompt: 分析提示

        Returns:
            分析结果列表
        """
        results = []

        for img_path in image_paths:
            if os.path.exists(img_path):
                result = self.client.chat(
                    text=analysis_prompt,
                    images=[img_path],
                    temperature=0.5,
                    top_k=12,
                    top_p=0.9
                )
                results.append({
                    "image": img_path,
                    "result": result
                })
            else:
                results.append({
                    "image": img_path,
                    "result": f"错误:文件不存在"
                })

        return results

    def compare_images(self, image1_path, image2_path, comparison_aspect="all"):
        """
        比较两张图像

        Args:
            image1_path: 第一张图像路径
            image2_path: 第二张图像路径
            comparison_aspect: 比较方面 (all, differences, similarities)

        Returns:
            比较结果
        """
        prompts = {
            "all": "请详细比较这两张图像,包括它们的相似之处和不同之处。请提供结构化的比较结果。",
            "differences": "请找出这两张图像之间的所有不同之处,并详细描述每个差异。",
            "similarities": "请找出这两张图像之间的所有相似之处,并详细描述每个相似点。"
        }

        prompt = prompts.get(comparison_aspect, prompts["all"])

        return self.client.chat(
            text=prompt,
            images=[image1_path, image2_path],
            temperature=0.4,
            top_k=10,
            top_p=0.9
        )

    def get_model_info(self):
        """
        获取模型信息

        Returns:
            模型信息
        """
        return self.client.chat(
            text="请介绍一下你的能力、特点和适用场景。",
            temperature=0.7,
            top_k=20,
            top_p=0.8
        )

def test_basic_chat():
    """测试基本文本对话"""
    print("=" * 50)
    print("测试基本文本对话")
    print("=" * 50)

    client = Qwen3VLClient()

    response = client.chat(
        text="请简单介绍一下 Qwen3-VL 模型的特点",
        temperature=0.7,
        top_k=20,
        top_p=0.8
    )

    if response and "choices" in response:
        print(f"模型回复:{response['choices'][0]['message']['content']}")
    else:
        print("请求失败")
    print()

def test_image_analysis():
    """测试图像分析"""
    print("=" * 50)
    print("测试图像分析")
    print("=" * 50)

    client = Qwen3VLClient()

    # 使用示例图像
    image_path = "example_image.jpg"

    if os.path.exists(image_path):
        response = client.chat(
            text="请详细描述这张图像的内容",
            images=[image_path],
            temperature=0.7,
            top_k=20,
            top_p=0.8
        )

        if response and "choices" in response:
            print(f"图像分析结果:{response['choices'][0]['message']['content']}")
        else:
            print("请求失败")
    else:
        print(f"图像文件不存在:{image_path}")
        print("提示:将图像文件放在脚本同目录下,命名为 example_image.jpg")
    print()

def test_conversation():
    """测试多轮对话"""
    print("=" * 50)
    print("测试多轮对话")
    print("=" * 50)

    client = Qwen3VLClient()

    # 初始对话历史
    history = []

    # 第一轮对话
    print("第一轮对话:")
    result1 = client.conversation_chat(
        conversation_history=history,
        new_message="我想了解人工智能的发展历史",
        temperature=0.7,
        top_k=20,
        top_p=0.8
    )
    print(f"用户:我想了解人工智能的发展历史")
    print(f"助手:{result1['reply'][:200]}...")  # 只显示前 200 个字符
    print()

    # 第二轮对话
    print("第二轮对话:")
    result2 = client.conversation_chat(
        conversation_history=result1['updated_history'],
        new_message="深度学习在哪个阶段开始兴起?",
        temperature=0.7,
        top_k=20,
        top_p=0.8
    )
    print(f"用户:深度学习在哪个阶段开始兴起?")
    print(f"助手:{result2['reply'][:200]}...")  # 只显示前 200 个字符
    print()

def test_developer_tools():
    """测试开发者工具"""
    print("=" * 50)
    print("测试开发者工具")
    print("=" * 50)

    dev_tool = QwenVLDeveloper()

    # 获取模型信息
    print("获取模型信息:")
    model_info = dev_tool.get_model_info()
    if model_info and "choices" in model_info:
        print(f"模型信息:{model_info['choices'][0]['message']['content'][:200]}...")
    print()

    # 测试带记忆的对话
    print("测试带记忆的对话:")
    reply1 = dev_tool.chat_with_memory("你好,请介绍一下自己")
    print(f"用户:你好,请介绍一下自己")
    print(f"助手:{reply1[:200]}...")

    reply2 = dev_tool.chat_with_memory("你能帮我分析图像吗?")
    print(f"用户:你能帮我分析图像吗?")
    print(f"助手:{reply2[:200]}...")
    print()

def test_document_analysis():
    """测试文档分析"""
    print("=" * 50)
    print("测试文档分析")
    print("=" * 50)

    dev_tool = QwenVLDeveloper()

    # 使用示例图像
    image_path = "example_image.jpg"

    if os.path.exists(image_path):
        # 全面分析
        print("全面分析文档:")
        result = dev_tool.analyze_document(
            image_path,
            analysis_type="comprehensive"
        )
        if result and "choices" in result:
            print(f"分析结果:{result['choices'][0]['message']['content'][:200]}...")
        print()

        # 仅提取文本
        print("仅提取文本:")
        result = dev_tool.analyze_document(
            image_path,
            analysis_type="text_only"
        )
        if result and "choices" in result:
            print(f"文本内容:{result['choices'][0]['message']['content'][:200]}...")
        print()
    else:
        print(f"图像文件不存在:{image_path}")
        print("提示:将图像文件放在脚本同目录下,命名为 example_image.jpg")
    print()

def test_code_generation():
    """测试 UI 设计转代码"""
    print("=" * 50)
    print("测试 UI 设计转代码")
    print("=" * 50)

    dev_tool = QwenVLDeveloper()

    # 使用示例图像
    image_path = "example_image.jpg"

    if os.path.exists(image_path):
        # 生成 HTML 代码
        print("生成 HTML 代码:")
        result = dev_tool.generate_code_from_ui(
            image_path,
            framework="html"
        )
        if result and "choices" in result:
            print(f"生成的 HTML 代码:{result['choices'][0]['message']['content'][:300]}...")
        print()
    else:
        print(f"图像文件不存在:{image_path}")
        print("提示:将图像文件放在脚本同目录下,命名为 example_image.jpg")
    print()

def test_educational_content():
    """测试教育内容生成"""
    print("=" * 50)
    print("测试教育内容生成")
    print("=" * 50)

    dev_tool = QwenVLDeveloper()

    # 使用示例图像
    image_path = "example_image.jpg"

    if os.path.exists(image_path):
        # 创建概念解释
        print("创建概念解释:")
        result = dev_tool.create_educational_content(
            image_path,
            content_type="explanation"
        )
        if result and "choices" in result:
            print(f"概念解释:{result['choices'][0]['message']['content'][:200]}...")
        print()

        # 创建测验题
        print("创建测验题:")
        result = dev_tool.create_educational_content(
            image_path,
            content_type="quiz"
        )
        if result and "choices" in result:
            print(f"测验题:{result['choices'][0]['message']['content'][:200]}...")
        print()
    else:
        print(f"图像文件不存在:{image_path}")
        print("提示:将图像文件放在脚本同目录下,命名为 example_image.jpg")
    print()

def test_batch_processing():
    """测试批量处理"""
    print("=" * 50)
    print("测试批量图像处理")
    print("=" * 50)

    dev_tool = QwenVLDeveloper()

    # 检查示例图像是否存在
    image_path = "example_image.jpg"

    if os.path.exists(image_path):
        # 创建图像列表(使用同一图像多次模拟批量处理)
        image_list = [image_path]

        # 定义分析提示
        analysis_prompt = "请简要描述这张图像的主要内容和特点"

        # 批量处理
        results = dev_tool.batch_analyze_images(image_list, analysis_prompt)

        # 查看结果
        for result in results:
            print(f"图像:{result['image']}")
            if isinstance(result['result'], dict) and "choices" in result['result']:
                print(f"分析结果:{result['result']['choices'][0]['message']['content'][:200]}...")
            else:
                print(f"分析结果:{result['result']}")
            print("-" * 30)
    else:
        print(f"图像文件不存在:{image_path}")
        print("提示:将图像文件放在脚本同目录下,命名为 example_image.jpg")
    print()

def test_image_comparison():
    """测试图像比较"""
    print("=" * 50)
    print("测试图像比较")
    print("=" * 50)

    dev_tool = QwenVLDeveloper()

    # 使用示例图像
    image_path = "example_image.jpg"

    if os.path.exists(image_path):
        # 使用同一图像进行比较(实际应用中应使用不同图像)
        print("比较两张图像(使用同一图像模拟):")
        comparison = dev_tool.compare_images(
            image_path,
            image_path,
            comparison_aspect="all"
        )

        if comparison and "choices" in comparison:
            print(f"比较结果:{comparison['choices'][0]['message']['content'][:200]}...")
    else:
        print(f"图像文件不存在:{image_path}")
        print("提示:将图像文件放在脚本同目录下,命名为 example_image.jpg")
    print()

def main():
    """主函数,运行所有测试"""
    print("Qwen3-VL API 综合测试")
    print("=" * 50)
    print("注意:图像相关测试需要 example_image.jpg 文件")
    print("=" * 50)
    print()

    # 运行所有测试
    test_basic_chat()
    test_image_analysis()
    test_conversation()
    test_developer_tools()
    test_document_analysis()
    test_code_generation()
    test_educational_content()
    test_batch_processing()
    test_image_comparison()

    print("=" * 50)
    print("测试完成!")
    print("=" * 50)
    print()
    print("使用说明:")
    print("1. 基本文本对话:使用 Qwen3VLClient.chat() 方法")
    print("2. 图像分析:在 chat() 方法中提供 images 参数")
    print("3. 多轮对话:使用 Qwen3VLClient.conversation_chat() 方法")
    print("4. 高级功能:使用 QwenVLDeveloper 类提供的方法")
    print("5. 详细文档:参考 README.md 文件")

if __name__ == "__main__":
    main()

使用指南

1. 环境准备

pip install requests pillow

2. 基本使用

from test_qwen3vl import Qwen3VLClient

client = Qwen3VLClient()

response = client.chat(
    text="你好,请介绍一下自己",
    temperature=0.7,
    top_k=20,
    top_p=0.8
)

if response and "choices" in response:
    print(f"模型回复:{response['choices'][0]['message']['content']}")

3. 图像分析

response = client.chat(
    text="请描述这张图片的内容",
    images=["path/to/image.jpg"],
    temperature=0.7,
    top_k=20,
    top_p=0.8
)

if response and "choices" in response:
    print(f"图像分析:{response['choices'][0]['message']['content']}")

4. 多轮对话

history = []

result1 = client.conversation_chat(
    conversation_history=history,
    new_message="我想了解人工智能",
    temperature=0.7,
    top_k=20,
    top_p=0.8
)

result2 = client.conversation_chat(
    conversation_history=result1['updated_history'],
    new_message="深度学习是什么?",
    temperature=0.7,
    top_k=20,
    top_p=0.8
)

5. 高级功能

from test_qwen3vl import QwenVLDeveloper

dev_tool = QwenVLDeveloper()

result = dev_tool.analyze_document(
    "document.jpg",
    analysis_type="comprehensive"
)

code = dev_tool.generate_code_from_ui(
    "ui_design.png",
    framework="html"
)

content = dev_tool.create_educational_content(
    "concept_diagram.jpg",
    content_type="explanation"
)

6. 运行完整测试

python test_qwen3vl.py

参数说明

参数 类型 默认值 说明
text str 必填 输入文本内容
images List[str] 可选 图像文件路径列表
conversation_history List[Dict] 可选 对话历史记录
model str “Qwen/Qwen3-VL-8B-Instruct-FP8” 模型名称
max_tokens int 2048 最大生成 token 数
temperature float 0.7 温度参数,控制随机性
top_k int 20 Top-K 采样参数
top_p float 0.8 Top-P 采样参数
stream bool False 是否使用流式输出

参数调优建议

  • 准确性任务(如文档分析): temperature=0.2, top_k=10, top_p=0.8
  • 创意性任务(如内容创作): temperature=0.9, top_k=30, top_p=0.95
  • 平衡性任务(如客服对话): temperature=0.6, top_k=20, top_p=0.9

注意事项

  1. 图像文件支持 JPG、PNG 等常见格式
  2. 图像大小建议不超过 10MB
  3. API 请求超时时间为 60 秒
  4. 建议在生产环境中添加错误处理和重试机制

故障排除

  1. 连接超时: 检查网络连接,增加超时时间
  2. 图像处理失败: 确认图像格式和大小是否符合要求
  3. API 响应错误: 检查请求参数是否正确,查看错误消息