{"id":37466697,"url":"https://github.com/cnblogs/dashscope-sdk","last_synced_at":"2026-04-18T17:09:36.049Z","repository":{"id":224883969,"uuid":"761627630","full_name":"cnblogs/dashscope-sdk","owner":"cnblogs","description":"An unofficial DashScope（ SDK for .NET maintained by Cnblogs.","archived":false,"fork":false,"pushed_at":"2026-04-16T14:16:18.000Z","size":8511,"stargazers_count":118,"open_issues_count":18,"forks_count":13,"subscribers_count":6,"default_branch":"main","last_synced_at":"2026-04-16T16:18:38.162Z","etag":null,"topics":["ai","bailian","dashscope-sdk","dotnet","qwen"],"latest_commit_sha":null,"homepage":"https://www.nuget.org/packages/Cnblogs.DashScope.AspNetCore","language":"C#","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/cnblogs.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2024-02-22T07:24:28.000Z","updated_at":"2026-04-03T03:19:40.000Z","dependencies_parsed_at":"2024-04-11T13:27:24.745Z","dependency_job_id":"dbd76d98-0d97-4578-9774-85eb22cd258d","html_url":"https://github.com/cnblogs/dashscope-sdk","commit_stats":null,"previous_names":["cnblogs/dashscopesdk","cnblogs/dashscope-sdk"],"tags_count":26,"template":false,"template_full_name":null,"purl":"pkg:github/cnblogs/dashscope-sdk","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cnblogs%2Fdashscope-sdk","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cnblogs%2Fdashscope-sdk/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cnblogs%2Fdashscope-sdk/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cnblogs%2Fdashscope-sdk/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/cnblogs","download_url":"https://codeload.github.com/cnblogs/dashscope-sdk/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cnblogs%2Fdashscope-sdk/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":31974955,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-18T00:39:45.007Z","status":"online","status_checked_at":"2026-04-18T02:00:07.018Z","response_time":103,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["ai","bailian","dashscope-sdk","dotnet","qwen"],"created_at":"2026-01-16T07:10:32.657Z","updated_at":"2026-04-18T17:09:36.041Z","avatar_url":"https://github.com/cnblogs.png","language":"C#","funding_links":[],"categories":[],"sub_categories":[],"readme":"English | [简体中文](https://github.com/cnblogs/dashscope-sdk/blob/main/README.zh-Hans.md)\n\n# Cnblogs.DashScopeSDK\n\n[![NuGet Version](https://img.shields.io/nuget/v/Cnblogs.DashScope.AI?style=flat\u0026logo=nuget\u0026label=Cnblogs.DashScope.AI)](https://www.nuget.org/packages/Cnblogs.DashScope.AI)\n[![NuGet Version](https://img.shields.io/nuget/v/Cnblogs.DashScope.Sdk?style=flat\u0026logo=nuget\u0026label=Cnblogs.DashScope.Sdk\u0026link=https%3A%2F%2Fwww.nuget.org%2Fpackages%2FCnblogs.DashScope.Sdk)](https://www.nuget.org/packages/Cnblogs.DashScope.Sdk)\n[![NuGet Version](https://img.shields.io/nuget/v/Cnblogs.DashScope.AspNetCore?style=flat\u0026logo=nuget\u0026label=Cnblogs.DashScope.AspNetCore\u0026link=https%3A%2F%2Fwww.nuget.org%2Fpackages%2FCnblogs.DashScope.AspNetCore)](https://www.nuget.org/packages/Cnblogs.DashScope.AspNetCore)\n\nA non-official DashScope (Bailian) service SDK maintained by Cnblogs.\n\n**Note:** This project is actively under development. Breaking changes may occur even in minor versions. Please review the Release Notes before upgrading.\n\n## Quick Start\n\n### Console Application\n\nInstall NuGet package `Cnblogs.DashScope.Sdk`\n```csharp\nvar client = new DashScopeClient(\"your-api-key\");\n// you could use different api base, example:\n// var client = new DashScopeClient(\"your-api-key\", \"https://dashscope-intl.aliyuncs.com/api/v1/\");\nvar completion = await client.GetTextCompletionAsync(\n    new ModelRequest\u003cTextGenerationInput, ITextGenerationParameters\u003e()\n    {\n        Model = \"qwen-turbo\",\n        Input = new TextGenerationInput()\n        {\n            Messages = new List\u003cTextChatMessage\u003e()\n            {\n                TextChatMessage.System(\"You are a helpful assistant\"),\n                TextChatMessage.User(\"你是谁？\")\n            }\n        },\n        Parameters = new TextGenerationParameters() { ResultFormat = \"message\" }\n    });\nConsole.WriteLine(completion.Output.Choices![0].Message.Content)\n```\n\n### ASP.NET Core Application\n\nInstall NuGet package `Cnblogs.DashScope.AspNetCore`\n\n`Program.cs`\n```csharp\nbuilder.AddDashScopeClient(builder.Configuration);\n```\n\n`appsettings.json`\n\n```json\n{\n    \"DashScope\": {\n        \"ApiKey\": \"your-api-key\",\n        \"BaseAddress\": \"https://dashscope-intl.aliyuncs.com/api/v1\"\n    }\n}\n```\n\nApplication class:\n\n```csharp\npublic class YourService(IDashScopeClient client)\n{\n    public async Task\u003cstring\u003e CompletePromptAsync(string prompt)\n    {\n    \tvar completion = await client.GetTextCompletionAsync(\n        new ModelRequest\u003cTextGenerationInput, ITextGenerationParameters\u003e()\n        {\n            Model = \"qwen-turbo\",\n            Input = new TextGenerationInput()\n            {\n                Messages = new List\u003cTextChatMessage\u003e()\n                {\n                    TextChatMessage.System(\"You are a helpful assistant\"),\n                    TextChatMessage.User(\"你是谁？\")\n                }\n            },\n            Parameters = new TextGenerationParameters() { ResultFormat = \"message\" }\n        });\n\t\treturn completion.Output.Choices![0].Message.Content\n    }\n}\n```\n### Using `Microsoft.Extensions.AI` Interface\n\nInstall NuGet package `Cnblogs.DashScope.AI`\n\n```csharp\nvar client = new DashScopeClient(\"your-api-key\").AsChatClient(\"qwen-max\");\nvar completion = await client.GetResponseAsync(\"hello\");\nConsole.WriteLine(completion.Text);\n```\n\n#### ToolCall\n\n```csharp\nvar chatClient = client.AsChatClient(\"qwen-turbo\").AsBuilder().UseFunctionInvocation().Build();\nvar options = new ChatOptions()\n{\n    Tools = [AIFunctionFactory.Create(GetWeather)],\n    ToolMode = new AutoChatToolMode(),\n    AllowMultipleToolCalls = true,\n};\nvar stream = chatClient.GetStreamingResponseAsync(\"What's weather today?\", options);\nawait foreach (var chatResponseUpdate in stream)\n{\n    Console.Write(chatResponseUpdate);\n}\n```\n\n#### Fallback to raw messages\n\nIf you need to use input data or parameters not supported by `Microsoft.Extensions.AI`, you can directly invoke the underlying SDK by passing a raw `TextChatMessage` or `MultimodalMessage` via `RawPresentation`.\n\nSimilarly, to pass unsupported parameters, you can also do so directly by setting the `raw` property within `AdditionalProperties`.\n\nExample(Using `qwen-doc-turbo`)\n\n```csharp\nvar messages = new List\u003cTextChatMessage\u003e()\n{\n    TextChatMessage.DocUrl(\n        \"从这两份产品手册中，提取所有产品信息，并整理成一个标准的JSON数组。每个对象需要包含：model(产品的型号)、name(产品的名称)、price(价格（去除货币符号和逗号）)\",\n        [\n            \"https://help-static-aliyun-doc.aliyuncs.com/file-manage-files/zh-CN/20251107/jockge/%E7%A4%BA%E4%BE%8B%E4%BA%A7%E5%93%81%E6%89%8B%E5%86%8CA.docx\",\n            \"https://help-static-aliyun-doc.aliyuncs.com/file-manage-files/zh-CN/20251107/ztwxzr/%E7%A4%BA%E4%BE%8B%E4%BA%A7%E5%93%81%E6%89%8B%E5%86%8CB.docx\"\n        ])\n};\nvar parameters = new TextGenerationParameters()\n{\n    ResultFormat = \"message\", IncrementalOutput = true,\n};\n\nvar response = client\n    .AsChatClient(\"qwen-doc-turbo\")\n    .GetStreamingResponseAsync(\n        messages.Select(x =\u003e new ChatMessage() { RawRepresentation = x }),\n        new ChatOptions()\n        {\n            AdditionalProperties = new AdditionalPropertiesDictionary() { { \"raw\", parameters } }\n        });\nawait foreach (var chunk in response)\n{\n    Console.Write(chunk.Text);\n}\n```\n\nSimilarly, you can also retrieve the raw message from the `RawPresentation` in the message returned by the model.\n\nExample (Getting the token count for an image when calling `qwen3-vl-plus`):\n\n```csharp\nvar response = client\n    .AsChatClient(\"qwen3-vl-plus\")\n    .GetStreamingResponseAsync(\n        new List\u003cChatMessage\u003e()\n        {\n            new(\n                ChatRole.User,\n                new List\u003cAIContent\u003e()\n                {\n                    new UriContent(\n                        \"https://help-static-aliyun-doc.aliyuncs.com/file-manage-files/zh-CN/20241022/emyrja/dog_and_girl.jpeg\",\n                        MediaTypeNames.Image.Jpeg),\n                    new UriContent(\n                        \"https://dashscope.oss-cn-beijing.aliyuncs.com/images/tiger.png\",\n                        MediaTypeNames.Image.Jpeg),\n                    new TextContent(\"这些图展现了什么内容？\")\n                })\n        },\n        new ChatOptions());\nvar lastChunk = (ChatResponseUpdate?)null;\nawait foreach (var chunk in response)\n{\n    Console.Write(chunk.Text);\n    lastChunk = chunk;\n}\n\nConsole.WriteLine();\n\n// Access underlying raw response\nvar raw = lastChunk?.RawRepresentation as ModelResponse\u003cMultimodalOutput, MultimodalTokenUsage\u003e;\nConsole.WriteLine($\"Image token usage: {raw?.Usage?.ImageTokens}\");\n```\n\n## Supported APIs\n\n- [Text Generation](#text-generation) - QWen3, DeepSeek, etc. Supports reasoning/tool calling/web search/translation scenarios\n  - [Conversation](#conversation)\n  - [Thinking Models](#thinking-models)\n  - [Web Search](#web-search)\n  - [Tool Calling](#tool-calling)\n  - [Prefix Completion](#prefix-completion)\n  - [Long Context (Qwen-Long)](#long-context-qwen-long)\n  - [Code Interpreter](#code-interpreter)\n- [Multimodal](#multimodal) - QWen-VL, QVQ, etc. Supports reasoning/visual understanding/OCR/audio understanding\n  - [Upload file for multimodal usage](#upload-file-for-multimodal-usage)\n  - [Image Recognition/Thinking](#image-recognition/thinking)\n  - [OCR](#ocr)\n    - [Advanced Recognition](#advanced-recognition)\n    - [Key Information Extraction](#key-information-extraction)\n    - [Table Parsing](#table-parsing)\n    - [Document Parsing](#document-parsing)\n    - [Formula Recognition](#formula-recognition)\n    - [Text Recognition](#text-recognition)\n    - [Multilanguage](#multilanguage)\n  - [GUI](#gui)\n  - [Audio Understanding](#audio-understanding)\n- [Text-to-Speech](#text-to-speech) - CosyVoice, Sambert, etc. For TTS applications\n- [Image Generation](#image-generation) - wanx2.1, etc. For text-to-image and portrait style transfer\n- [Application Call](#application-call)\n- [Batch](#batch)\n- [Text Embeddings](#text-embeddings)\n\n\n## Text Generation\n\nUse `dashScopeClient.GetTextCompletionAsync` and `dashScopeClient.GetTextCompletionStreamAsync()` to access text generation APIs.\n\nCommon models: `qwen-max` `qwen-plus` `qwen-flush` etc.\n\nBasic example:\n\n```csharp\nvar client = new DashScopeClient(\"your-api-key\");\nvar completion = await client.GetTextCompletionAsync(\n    new ModelRequest\u003cTextGenerationInput, ITextGenerationParameters\u003e()\n    {\n        Model = \"qwen-turbo\",\n        Input = new TextGenerationInput()\n        {\n            Messages = new List\u003cTextChatMessage\u003e()\n            {\n                TextChatMessage.System(\"You are a helpful assistant\"),\n                TextChatMessage.User(\"Who are you?\")\n            }\n        },\n        Parameters = new TextGenerationParameters() { ResultFormat = \"message\" }\n    });\nConsole.WriteLine(completion.Output.Choices![0].Message.Content)\n```\n\n### Conversation\n\n#### Quick Start\n\nThe key is maintaining a `TextChatMessage` array as conversation history.\n\n```csharp\nvar messages = new List\u003cTextChatMessage\u003e();\nmessages.Add(TextChatMessage.System(\"You are a helpful assistant\"));\nwhile (true)\n{\n    Console.Write(\"User \u003e \");\n    var input = Console.ReadLine();\n    if (string.IsNullOrEmpty(input))\n    {\n        Console.WriteLine(\"Using default input: Who are you?\");\n        input = \"Who are you?\";\n    }\n\n    messages.Add(TextChatMessage.User(input));\n    var completion = await client.GetTextCompletionAsync(\n        new ModelRequest\u003cTextGenerationInput, ITextGenerationParameters\u003e()\n        {\n            Model = \"qwen-turbo\",\n            Input = new TextGenerationInput() { Messages = messages },\n            Parameters = new TextGenerationParameters() { ResultFormat = \"message\" }\n        });\n    Console.WriteLine(\"Assistant \u003e \" + completion.Output.Choices![0].Message.Content);\n    var usage = completion.Usage;\n    if (usage != null)\n    {\n        Console.WriteLine($\"Usage: in({usage.InputTokens})/out({usage.OutputTokens})/total({usage.TotalTokens})\");\n    }\n\n    messages.Add(TextChatMessage.Assistant(completion.Output.Choices[0].Message.Content));\n}\n```\n\n### Thinking Models\n\nThe model's thinking process is stored in a separate `ReasoningContent` property. When saving to conversation history, ignore it and only keep the model's reply `Content`.\n\nSome models accept `EnableThinking` to control deep thinking, which can be set in `Parameters`.\n\n```csharp\nvar messages = new List\u003cTextChatMessage\u003e();\nmessages.Add(TextChatMessage.System(\"You are a helpful assistant\"));\nwhile (true)\n{\n    Console.Write(\"User \u003e \");\n    var input = Console.ReadLine();\n    if (string.IsNullOrEmpty(input))\n    {\n        Console.WriteLine(\"Please enter a user input.\");\n        return;\n    }\n\n    messages.Add(TextChatMessage.User(input));\n    var completion = await client.GetTextCompletionAsync(\n        new ModelRequest\u003cTextGenerationInput, ITextGenerationParameters\u003e()\n        {\n            Model = \"qwen-turbo\",\n            Input = new TextGenerationInput() { Messages = messages },\n            Parameters = new TextGenerationParameters() { ResultFormat = \"message\", EnableThinking = true }\n        });\n    Console.WriteLine(\"Reasoning \u003e \" + completion.Output.Choices![0].Message.ReasoningContent);\n    Console.WriteLine(\"Assistant \u003e \" + completion.Output.Choices![0].Message.Content);\n    var usage = completion.Usage;\n    if (usage != null)\n    {\n        Console.WriteLine(\n            $\"Usage: in({usage.InputTokens})/out({usage.OutputTokens})/reasoning({usage.OutputTokensDetails?.ReasoningTokens})/total({usage.TotalTokens})\");\n    }\n\n    messages.Add(TextChatMessage.Assistant(completion.Output.Choices[0].Message.Content));\n}\n```\n\n#### Streaming Output\n\n```cs\nvar request = new ModelRequest\u003cTextGenerationInput, ITextGenerationParameters\u003e()\n{\n    Model = \"qwen-turbo\",\n    Input = new TextGenerationInput() { Messages = messages },\n    Parameters = new TextGenerationParameters()\n    {\n        ResultFormat = \"message\",\n        EnableThinking = true,\n        IncrementalOutput = true\n    }\n}\n```\n\nUse `client.GetTextCompletionStreamAsync` for streaming output. It's recommended to enable `IncrementalOutput` in `Parameters` for incremental output.\n\nIncremental output:\n\u003e Example: [\"I love\",\"eating\",\"apples\"]\n\nNon-incremental output:\n\u003e Example: [\"I love\",\"I love eating\",\"I love eating apples\"]\n\nStreaming output returns an `IAsyncEnumerable`. Use `await foreach` to iterate, record incremental content, then save to conversation history.\n\nvar messages = new List\u003cTextChatMessage\u003e();\nmessages.Add(TextChatMessage.System(\"You are a helpful assistant\"));\nwhile (true)\n{\n    Console.Write(\"User \u003e \");\n    var input = Console.ReadLine();\n    if (string.IsNullOrEmpty(input))\n    {\n        Console.WriteLine(\"Please enter a user input.\");\n        return;\n    }\n\n    messages.Add(TextChatMessage.User(input));\n    var completion = client.GetTextCompletionStreamAsync(\n        new ModelRequest\u003cTextGenerationInput, ITextGenerationParameters\u003e()\n        {\n            Model = \"qwen-turbo\",\n            Input = new TextGenerationInput() { Messages = messages },\n            Parameters = new TextGenerationParameters()\n            {\n                ResultFormat = \"message\",\n                EnableThinking = true,\n                IncrementalOutput = true\n            }\n        });\n    var reply = new StringBuilder();\n    var reasoning = false;\n    TextGenerationTokenUsage? usage = null;\n    await foreach (var chunk in completion)\n    {\n        var choice = chunk.Output.Choices![0];\n        if (string.IsNullOrEmpty(choice.Message.ReasoningContent) == false)\n        {\n            // reasoning\n            if (reasoning == false)\n            {\n                Console.Write(\"Reasoning \u003e \");\n                reasoning = true;\n            }\n\n            Console.Write(choice.Message.ReasoningContent);\n            continue;\n        }\n\n        if (reasoning)\n        {\n            reasoning = false;\n            Console.WriteLine();\n            Console.Write(\"Assistant \u003e \");\n        }\n\n        Console.Write(choice.Message.Content);\n        reply.Append(choice.Message.Content);\n        usage = chunk.Usage;\n    }\n\n    Console.WriteLine();\n    messages.Add(TextChatMessage.Assistant(reply.ToString()));\n    if (usage != null)\n    {\n        Console.WriteLine(\n            $\"Usage: in({usage.InputTokens})/out({usage.OutputTokens})/reasoning({usage.OutputTokensDetails?.ReasoningTokens})/total({usage.TotalTokens})\");\n    }\n}\n\n#### Limiting Thinking Length\n\nUse `ThinkingBudget` in `Parameters` to limit the model's thinking length.\n\n```cs\nconst int budget = 10;\nConsole.WriteLine($\"Set thinking budget to {budget} tokens\");\nvar messages = new List\u003cTextChatMessage\u003e();\nmessages.Add(TextChatMessage.System(\"You are a helpful assistant\"));\nwhile (true)\n{\n    Console.Write(\"User \u003e \");\n    var input = Console.ReadLine();\n    if (string.IsNullOrEmpty(input))\n    {\n        Console.WriteLine(\"Please enter a user input.\");\n        return;\n    }\n\n    messages.Add(TextChatMessage.User(input));\n    var completion = client.GetTextCompletionStreamAsync(\n        new ModelRequest\u003cTextGenerationInput, ITextGenerationParameters\u003e()\n        {\n            Model = \"qwen-turbo\",\n            Input = new TextGenerationInput() { Messages = messages },\n            Parameters = new TextGenerationParameters()\n            {\n                ResultFormat = \"message\",\n                EnableThinking = true,\n                ThinkingBudget = budget,\n                IncrementalOutput = true\n            }\n        });\n    var reply = new StringBuilder();\n    var reasoning = false;\n    TextGenerationTokenUsage? usage = null;\n    await foreach (var chunk in completion)\n    {\n        var choice = chunk.Output.Choices![0];\n        if (string.IsNullOrEmpty(choice.Message.ReasoningContent) == false)\n        {\n            // reasoning\n            if (reasoning == false)\n            {\n                Console.Write(\"Reasoning \u003e \");\n                reasoning = true;\n            }\n\n            Console.Write(choice.Message.ReasoningContent);\n            continue;\n        }\n\n        if (reasoning)\n        {\n            reasoning = false;\n            Console.WriteLine();\n            Console.Write(\"Assistant \u003e \");\n        }\n\n        Console.Write(choice.Message.Content);\n        reply.Append(choice.Message.Content);\n        usage = chunk.Usage;\n    }\n\n    Console.WriteLine();\n    messages.Add(TextChatMessage.Assistant(reply.ToString()));\n    if (usage != null)\n    {\n        Console.WriteLine(\n            $\"Usage: in({usage.InputTokens})/out({usage.OutputTokens})/reasoning({usage.OutputTokensDetails?.ReasoningTokens})/total({usage.TotalTokens})\");\n    }\n}\n```\n\n### Web Search\n\nControlled mainly through `EnableSearch` and `SearchOptions` in `Parameters`.\n\nExample request:\n\n```cs\nvar request = new ModelRequest\u003cTextGenerationInput, ITextGenerationParameters\u003e()\n{\n    Model = \"qwen-turbo\",\n    Input = new TextGenerationInput() { Messages = messages },\n    Parameters = new TextGenerationParameters()\n    {\n        ResultFormat = \"message\",\n        EnableThinking = true,\n        EnableSearch = true,\n        SearchOptions = new TextGenerationSearchOptions()\n        {\n            SearchStrategy = \"max\", // max/turbo - controls number of search results\n            EnableCitation = true,  // Add source citations to model reply\n            CitationFormat = \"[ref_\u003cnumber\u003e]\", // Citation format\n            EnableSource = true, // Return search source list in SearchInfo\n            ForcedSearch = true, // Force model to search\n            EnableSearchExtension = true, // Enable vertical domain search, results in SearchInfo.Extra\n            PrependSearchResult = true // First packet contains only search results\n        }\n    }\n};\n```\n\n### Tool Calling\n\nProvide available tools to the model via `Tools` in `Parameters`. The model returns messages with `ToolCall` properties to invoke tools.\n\nAfter receiving the message, the server needs to call the corresponding tools and insert results as `Tool` role messages into the conversation history before making another request. The model will summarize the tool call results.\n\nBy default, the model calls tools once per turn. To enable multiple tool calls, enable `ParallelToolCalls` in `Parameters`.\n\n```\nvar tools = new List\u003cToolDefinition\u003e\n{\n    new(\n        ToolTypes.Function,\n        new FunctionDefinition(\n            nameof(GetWeather),\n            \"Get current weather\",\n            new JsonSchemaBuilder().FromType\u003cWeatherReportParameters\u003e().Build()))\n};\n\nvar request = new ModelRequest\u003cTextGenerationInput, ITextGenerationParameters\u003e()\n{\n    Model = \"qwen-turbo\",\n    Input = new TextGenerationInput() { Messages = messages },\n    Parameters = new TextGenerationParameters()\n    {\n        ResultFormat = \"message\",\n        EnableThinking = true,\n        IncrementalOutput = true,\n        Tools = tools,\n        ToolChoice = ToolChoice.AutoChoice,\n        ParallelToolCalls = true // Model can call multiple tools at once\n    }\n}\n```\n\n### Structured Output (JSON Output)\n\nSet `ResponseFormat` (remarks: **not** `ResultFormat`) in `Parameters` to JSON to force JSON output.\n\n```csharp\nvar request = new ModelRequest\u003cTextGenerationInput, ITextGenerationParameters\u003e()\n{\n    Model = \"qwen-plus\",\n    Input = new TextGenerationInput() { Messages = messages },\n    Parameters = new TextGenerationParameters()\n    {\n        ResultFormat = \"message\",\n        ResponseFormat = DashScopeResponseFormat.Json,\n        IncrementalOutput = true\n    }\n}\n```\n\n### Prefix Completion\n\nPlace the prefix to complete as an `assistant` message at the end of the `messages` array with `Partial` set to `true`. The model will complete the remaining content based on this prefix.\n\nDeep thinking cannot be enabled in this mode.\n\n```cs\nvar messages = new List\u003cTextChatMessage\u003e\n{\n    TextChatMessage.User(\"Complete following C# method.\"),\n    TextChatMessage.Assistant(\"public int Fibonacci(int n)\", partial: true)\n};\n\nvar completion = client.GetTextCompletionStreamAsync(\nnew ModelRequest\u003cTextGenerationInput, ITextGenerationParameters\u003e()\n{\n    Model = \"qwen-turbo\",\n    Input = new TextGenerationInput() { Messages = messages },\n    Parameters = new TextGenerationParameters()\n    {\n        ResultFormat = \"message\",\n        IncrementalOutput = true\n    }\n});\n```\n\n### Long Context (Qwen-Long)\nFor Qwen-Long models:\n```csharp\nvar file = new FileInfo(\"test.txt\");\nvar uploadedFile = await dashScopeClient.OpenAiCompatibleUploadFileAsync(file.OpenRead(), file.Name);\nvar history = new List\u003cChatMessage\u003e { ChatMessage.File(uploadedFile.Id) };\nvar completion = await client.client.GetTextCompletionAsync(\n        new ModelRequest\u003cTextGenerationInput, ITextGenerationParameters\u003e()\n        {\n            Model = \"qwen-long\",\n            Input = new TextGenerationInput() { Messages = history },\n            Parameters = new TextGenerationParameters()\n            {\n                ResultFormat = \"message\",\n                EnableThinking = false,\n            }\n        });\nConsole.WriteLine(completion.Output.Choices[0].Message.Content);\n// Cleanup\nawait dashScopeClient.OpenAiCompatibleDeleteFileAsync(uploadedFile.Id);\n```\n\n### Code Interpreter\n\n**This capability is mutually exclusive with Function Call and cannot be used simultaneously.**\n\nUse the `EnableCodeInterpreter` parameter in `Parameters` to allow the model to write code and call an internal code interpreter for calculations.\n\nExample Request:\n\n```csharp\nvar completion = client.GetTextCompletionStreamAsync(\n    new ModelRequest\u003cTextGenerationInput, ITextGenerationParameters\u003e()\n    {\n        Model = \"qwen3-max-preview\",\n        Input = new TextGenerationInput() { Messages = messages },\n        Parameters = new TextGenerationParameters()\n        {\n            ResultFormat = \"message\",\n            EnableThinking = true,\n            EnableCodeInterpreter = true,\n            IncrementalOutput = true\n        }\n    });\n```\n\nThe code that model generated will be included in `chunk.Output.ToolInfo.CodeInterpreter`. The invocation process can be considered part of the reasoning process.\n\nFull example,\n\n```csharp\nvar messages = new List\u003cTextChatMessage\u003e();\nconst string input = \"123的21次方是多少？\";\nConsole.Write($\"User \u003e {input}\");\nmessages.Add(TextChatMessage.User(input));\nvar completion = client.GetTextCompletionStreamAsync(\n    new ModelRequest\u003cTextGenerationInput, ITextGenerationParameters\u003e\n    {\n        Model = \"qwen3-max-preview\",\n        Input = new TextGenerationInput { Messages = messages },\n        Parameters = new TextGenerationParameters\n        {\n            ResultFormat = \"message\",\n            EnableThinking = true,\n            EnableCodeInterpreter = true,\n            IncrementalOutput = true\n        }\n    });\nvar reply = new StringBuilder();\nvar codeGenerated = false;\nvar reasoning = false;\nTextGenerationTokenUsage? usage = null;\nawait foreach (var chunk in completion)\n{\n    var choice = chunk.Output.Choices![0];\n    var tool = chunk.Output.ToolInfo?.FirstOrDefault();\n    if (codeGenerated == false \u0026\u0026 tool?.CodeInterpreter != null)\n    {\n        Console.WriteLine($\"Code \u003e {tool.CodeInterpreter.Code}\");\n        codeGenerated = true;\n    }\n\n    if (string.IsNullOrEmpty(choice.Message.ReasoningContent) == false)\n    {\n        // reasoning\n        if (reasoning == false)\n        {\n            Console.WriteLine();\n            Console.Write(\"Reasoning \u003e \");\n            reasoning = true;\n        }\n\n        Console.Write(choice.Message.ReasoningContent);\n        continue;\n    }\n\n    if (reasoning \u0026\u0026 string.IsNullOrEmpty(choice.Message.Content.Text) == false)\n    {\n        reasoning = false;\n        Console.WriteLine();\n        Console.Write(\"Assistant \u003e \");\n    }\n\n    Console.Write(choice.Message.Content);\n    reply.Append(choice.Message.Content);\n    usage = chunk.Usage;\n}\n\nConsole.WriteLine();\nmessages.Add(TextChatMessage.Assistant(reply.ToString()));\nif (usage != null)\n{\n    Console.WriteLine(\n        $\"Usage: in({usage.InputTokens})/out({usage.OutputTokens})/reasoning({usage.OutputTokensDetails?.ReasoningTokens})/plugins({usage.Plugins?.CodeInterpreter?.Count})/total({usage.TotalTokens})\");\n}\n\n/*\nUser \u003e 123的21次方是多少？\nReasoning \u003e 用户问的是123的21次方是多少。这是一个大数计算问题，我需要使用代码计算器来计算这个值。\n\n我需要调用code_interpreter函数，传入计算123**21的Python代码。\n123**21\n用户询问123的21次方是多少，我使用代码计算器计算出了结果。结果是一个非常大的数字：77269364466549865653073473388030061522211723\n\n我应该直接给出这个结果，因为这是一个精确的数学计算问题，不需要额外的解释或\nAssistant \u003e 123的21次方是：77269364466549865653073473388030061522211723\nUsage: in(704)/out(234)/reasoning(142)/plugins(1)/total(938)\n*/\n```\n\n\n\n## Multimodal\n\nUse `GetMultimodalGenerationAsync`/`GetMultimodalGenerationStreamAsync`\n[Official Documentation](https://help.aliyun.com/zh/model-studio/multimodal)\n\n### Upload file for multimodal usage\n\nYou can upload file to get an oss link before multimodal usage.\n\n```csharp\nawait using var video = File.OpenRead(\"sample.mp4\");\nvar ossLink = await client.UploadTemporaryFileAsync(\"qwen3-vl-plus\", video, \"sample.mp4\");\nConsole.WriteLine($\"File uploaded: {ossLink}\");\n\nvar messages = new List\u003cMultimodalMessage\u003e();\nmessages.Add(\n    MultimodalMessage.User(\n    [\n        MultimodalMessageContent.VideoContent(ossLink, fps: 2),\n        // MultimodalMessageContent.VideoFrames(links),\n        // MultimodalMessageContent.ImageContent(link)\n        MultimodalMessageContent.TextContent(\"这段视频的内容是什么？\")\n    ]));\n```\n\n### Image recognition/thinking\n\n```csharp\nvar image = await File.ReadAllBytesAsync(\"Lenna.jpg\");\nvar response = dashScopeClient.GetMultimodalGenerationStreamAsync(\n    new ModelRequest\u003cMultimodalInput, IMultimodalParameters\u003e()\n    {\n        Model = \"qvq-plus\",\n        Input = new MultimodalInput()\n        {\n            Messages =\n            [\n                MultimodalMessage.User(\n                [\n                    MultimodalMessageContent.ImageContent(image, \"image/jpeg\"),\n                    MultimodalMessageContent.TextContent(\"她是谁？\")\n                ])\n            ]\n        },\n        Parameters =\n            new MultimodalParameters\n            {\n                IncrementalOutput = true,\n                // EnableThinking = true,\n                VlHighResolutionImages = false\n            }\n    });\n\n// output\nvar reasoning = false;\nawait foreach (var modelResponse in response)\n{\n    var choice = modelResponse.Output.Choices.FirstOrDefault();\n    if (choice != null)\n    {\n        if (choice.FinishReason != \"null\")\n        {\n            break;\n        }\n\n        if (string.IsNullOrEmpty(choice.Message.ReasoningContent) == false)\n        {\n            if (reasoning == false)\n            {\n                reasoning = true;\n                Console.WriteLine(\"\u003cthink\u003e\");\n            }\n\n            Console.Write(choice.Message.ReasoningContent);\n            continue;\n        }\n\n        if (reasoning)\n        {\n            reasoning = false;\n            Console.WriteLine(\"\u003c/think\u003e\");\n        }\n\n        Console.Write(choice.Message.Content[0].Text);\n    }\n}\n```\n\n### OCR\n\nBase example of OCR\n\n```csharp\n// upload file\nawait using var tilted = File.OpenRead(\"tilted.png\");\nvar ossLink = await client.UploadTemporaryFileAsync(\"qwen-vl-ocr-latest\", tilted, \"tilted.jpg\");\nConsole.WriteLine($\"File uploaded: {ossLink}\");\nvar messages = new List\u003cMultimodalMessage\u003e();\nmessages.Add(\n    MultimodalMessage.User(\n    [\n        // set enableRotate to true if your source image is tilted.\n        MultimodalMessageContent.ImageContent(ossLink, enableRotate: true),\n    ]));\nvar completion = client.GetMultimodalGenerationStreamAsync(\n    new ModelRequest\u003cMultimodalInput, IMultimodalParameters\u003e()\n    {\n        Model = \"qwen-vl-ocr-latest\",\n        Input = new MultimodalInput() { Messages = messages },\n        Parameters = new MultimodalParameters()\n        {\n            IncrementalOutput = true,\n        }\n    });\nvar reply = new StringBuilder();\nvar first = false;\nMultimodalTokenUsage? usage = null;\nawait foreach (var chunk in completion)\n{\n    var choice = chunk.Output.Choices[0];\n    if (first)\n    {\n        first = false;\n        Console.Write(\"Assistant \u003e \");\n    }\n\n    if (choice.Message.Content.Count == 0)\n    {\n        continue;\n    }\n\n    Console.Write(choice.Message.Content[0].Text);\n    reply.Append(choice.Message.Content[0].Text);\n    usage = chunk.Usage;\n}\n\nConsole.WriteLine();\nmessages.Add(MultimodalMessage.Assistant([MultimodalMessageContent.TextContent(reply.ToString())]));\nif (usage != null)\n{\n    Console.WriteLine(\n        $\"Usage: in({usage.InputTokens})/out({usage.OutputTokens})/image({usage.ImageTokens})/total({usage.TotalTokens})\");\n}\n```\n\n#### Built-in Tasks\n\n##### Advanced Recognition\n\nWhen using this task, do not enable streaming. Otherwise, `completion.Output.Choices[0].Message.Content[0].OcrResult.WordsInfo` will be `null`.\n\nIn addition to the standard text content, this task also returns the coordinates of the text.\n\nTo call this built-in task, set `Parameters.OcrOptions.Task` to `advanced_recognition`. No additional prompt is required.\n\n![](sample/Cnblogs.DashScope.Sample/tilted.png)\n\n```csharp\nvar messages = new List\u003cMultimodalMessage\u003e();\nmessages.Add(\n    MultimodalMessage.User(\n    [\n        MultimodalMessageContent.ImageContent(ossLink),\n    ]));\nvar completion = client.GetMultimodalGenerationAsync(\n    new ModelRequest\u003cMultimodalInput, IMultimodalParameters\u003e()\n    {\n        Model = \"qwen-vl-ocr-latest\",\n        Input = new MultimodalInput() { Messages = messages },\n        Parameters = new MultimodalParameters()\n        {\n            OcrOptions = new MultimodalOcrOptions()\n            {\n                Task = \"advanced_recognition\"\n            }\n        }\n    });\n```\n\nOutput usage:\n\n```csharp\nConsole.WriteLine(\"Text:\");\nConsole.WriteLine(completion.Output.Choices[0].Message.Content[0].Text);\nConsole.WriteLine(\"WordsInfo:\");\nforeach (var info in completion.Output.Choices[0].Message.Content[0].OcrResult!.WordsInfo!)\n{\n    var location = $\"[{string.Join(',', info.Location)}]\";\n    var rect = $\"[{string.Join(',', info.RotateRect)}]\";\n    Console.WriteLine(info.Text);\n    Console.WriteLine($\"Location: {location}\");\n    Console.WriteLine($\"RotateRect: {rect}\");\n    Console.WriteLine();\n}\n```\n\nOutput:\n\n````csharp\nText:\n```json\n[\n        {\"rotate_rect\": [236, 254, 115, 299, 90], \"text\": \"OpenAI 兼容\"},\n        {\"rotate_rect\": [646, 254, 115, 269, 90], \"text\": \"DashScope\"},\n        {\"rotate_rect\": [236, 684, 115, 163, 90], \"text\": \"Python\"},\n        {\"rotate_rect\": [492, 684, 115, 105, 90], \"text\": \"Java\"},\n        {\"rotate_rect\": [712, 684, 115, 85, 90], \"text\": \"curl\"}\n]\n```\nWordsInfo:\nOpenAI 兼容\nLocation: [46,55,205,55,205,87,46,87]\nRotateRect: [125,71,159,32,0]\n\nDashScope\nLocation: [272,55,415,55,415,87,272,87]\nRotateRect: [344,71,32,143,90]\n\nPython\nLocation: [82,175,169,175,169,207,82,207]\nRotateRect: [126,191,32,87,90]\n\nJava\nLocation: [234,175,289,175,289,207,234,207]\nRotateRect: [262,191,55,32,0]\n\ncurl\nLocation: [356,175,401,175,401,207,356,207]\nRotateRect: [378,191,32,45,90]\n````\n\n##### Key Information Extraction\n\nWhen using built-in tasks, it is not recommended to enable streaming; otherwise, `completion.Output.Choices[0].Message.Content[0].OcrResult.KvResult` will be `null`.\n\nTo invoke this built-in task, set `Parameters.OcrOptions.Task` to `key_information_extraction`. No additional text information needs to be provided.\n\nYou can customize the output JSON format via `Parameters.OcrOptions.TaskConfig.ResultSchema` (with a maximum of 3 levels of nesting). If left blank, all fields will be output by default.\n\nFor example, suppose we want to extract objects of the following type from an image (JSON property names should, as much as possible, be based on the text present in the image):\n\n![](sample/Cnblogs.DashScope.Sample/receipt.jpg)\n\n```csharp\ninternal class ReceiptModel()\n{\n    [JsonPropertyName(\"乘车日期\")]\n    public string? Date { get; init; }\n\n    [JsonPropertyName(\"发票\")]\n    public ReceiptSerials? Serials { get; init; }\n}\n\ninternal class ReceiptSerials\n{\n    [JsonPropertyName(\"发票代码\")]\n    public string? Code { get; init; }\n\n    [JsonPropertyName(\"发票号码\")]\n    public string? Serial { get; init; }\n}\n```\n\nProperty could be `null` if model failed to extract value for it.\nExample request:\n\n```csharp\nawait using var file = File.OpenRead(\"receipt.jpg\");\nvar ossLink = await client.UploadTemporaryFileAsync(\"qwen-vl-ocr-latest\", file, \"receipt.jpg\");\nConsole.WriteLine($\"File uploaded: {ossLink}\");\nvar messages =\n    new List\u003cMultimodalMessage\u003e { MultimodalMessage.User([MultimodalMessageContent.ImageContent(ossLink)]) };\nvar completion = await client.GetMultimodalGenerationAsync(\n    new ModelRequest\u003cMultimodalInput, IMultimodalParameters\u003e()\n    {\n        Model = \"qwen-vl-ocr-latest\",\n        Input = new MultimodalInput() { Messages = messages },\n        Parameters = new MultimodalParameters()\n        {\n            OcrOptions = new MultimodalOcrOptions()\n            {\n                Task = \"key_information_extraction\",\n                TaskConfig = new MultimodalOcrTaskConfig()\n                {\n                    ResultSchema = new Dictionary\u003cstring, object\u003e()\n                    {\n                        {\n                            \"发票\",\n                            new Dictionary\u003cstring, string\u003e()\n                            {\n                                { \"发票代码\", \"提取图中的发票代码，通常为一组数字或字母组合\" },\n                                { \"发票号码\", \"提取发票上的号码，通常由纯数字组成。\" }\n                            }\n                        },\n                        { \"乘车日期\", \"对应图中乘车日期时间，格式为年-月-日，比如2025-03-05\" }\n                    }\n                }\n            }\n        }\n    });\n```\n\nConsume:\n\n`KvResult` is `JsonElement`，you can deserialize it to any type you desire, or you could just use `Dictionary\u003cstring, JsonElement?\u003e` .\n\n````csharp\nConsole.WriteLine(\"Text:\");\nConsole.WriteLine(completion.Output.Choices[0].Message.Content[0].Text);\nConsole.WriteLine(\"KvResults:\");\nvar model = completion.Output.Choices[0].Message.Content[0].OcrResult!.KvResult?.Deserialize\u003cReceiptModel\u003e();\nConsole.WriteLine($\"Date: {model?.Date}\");\nConsole.WriteLine($\"Code: {model?.Serials?.Code}\");\nConsole.WriteLine($\"Serial: {model?.Serials?.Serial}\");\n\n/*\nText:\n```json\n{\n    \"乘车日期\": \"2013-06-29\",\n    \"发票\": {\n        \"发票代码\": \"221021325353\",\n        \"发票号码\": \"10283819\"\n    }\n}\n```\nKvResults:\nDate: 2013-06-29\nCode: 221021325353\nSerial: 10283819\nUsage: in(524)/out(65)/image(310)/total(589)\n*/\n````\n\n##### Table Parsing\n\nTo invoke this built-in task, set `Parameters.OcrOptions.Task` to `table_parsing`. No additional text information needs to be provided.\n\nThis task will extract tables from images and return them in HTML format.\n\nExample:\n\n![](sample/Cnblogs.DashScope.Sample/table.jpg)\n\n```csharp\nawait using var file = File.OpenRead(\"table.jpg\");\nvar ossLink = await client.UploadTemporaryFileAsync(\"qwen-vl-ocr-latest\", file, \"table.jpg\");\nConsole.WriteLine($\"File uploaded: {ossLink}\");\nvar messages =\n    new List\u003cMultimodalMessage\u003e { MultimodalMessage.User([MultimodalMessageContent.ImageContent(ossLink)]) };\nvar completion = await client.GetMultimodalGenerationAsync(\n    new ModelRequest\u003cMultimodalInput, IMultimodalParameters\u003e()\n    {\n        Model = \"qwen-vl-ocr-latest\",\n        Input = new MultimodalInput { Messages = messages },\n        Parameters = new MultimodalParameters()\n        {\n            OcrOptions = new MultimodalOcrOptions()\n            {\n                Task = \"table_parsing\",\n            }\n        }\n    });\n\nConsole.WriteLine(completion.Output.Choices[0].Message.Content[0].Text);\n```\n\nReturn value(Model would wrap the html code in a markdown code fence):\n\n````markdown\n```html\n\u003ctable\u003e\n  \u003ctr\u003e\n    \u003ctd\u003eRecord of test data\u003c/td\u003e\n  \u003c/tr\u003e\n  \u003ctr\u003e\n    \u003ctd\u003eProject name：2B\u003c/td\u003e\n    \u003ctd\u003eControl No.CEPRI-D-JS1-JS-057-2022-003\u003c/td\u003e\n  \u003c/tr\u003e\n  \u003ctr\u003e\n    \u003ctd\u003eCase name\u003c/td\u003e\n    \u003ctd\u003eTest No.3 Conductor rupture GL+GR(max angle)\u003c/td\u003e\n    \u003ctd\u003eLast load grade：\u003c/td\u003e\n    \u003ctd\u003e0%\u003c/td\u003e\n    \u003ctd\u003eCurrent load grade：\u003c/td\u003e\n  \u003c/tr\u003e\n  \u003ctr\u003e\n    \u003ctd\u003eMeasure\u003c/td\u003e\n    \u003ctd\u003eLoad point\u003c/td\u003e\n    \u003ctd\u003eLoad method\u003c/td\u003e\n    \u003ctd\u003eActual Load(%)\u003c/td\u003e\n    \u003ctd\u003eActual Load(kN)\u003c/td\u003e\n  \u003c/tr\u003e\n  \u003ctr\u003e\n    \u003ctd\u003echannel\u003c/td\u003e\n    \u003ctd\u003eV1\u003c/td\u003e\n    \u003ctd\u003e活载荷\u003c/td\u003e\n    \u003ctd\u003e147.95\u003c/td\u003e\n    \u003ctd\u003e0.815\u003c/td\u003e\n  \u003c/tr\u003e\n  \u003ctr\u003e\n    \u003ctd\u003eV03\u003c/td\u003e\n    \u003ctd\u003eV2\u003c/td\u003e\n    \u003ctd\u003e活载荷\u003c/td\u003e\n    \u003ctd\u003e111.75\u003c/td\u003e\n    \u003ctd\u003e0.615\u003c/td\u003e\n  \u003c/tr\u003e\n  \u003ctr\u003e\n    \u003ctd\u003eV04\u003c/td\u003e\n    \u003ctd\u003eV3\u003c/td\u003e\n    \u003ctd\u003e活载荷\u003c/td\u003e\n    \u003ctd\u003e9.74\u003c/td\u003e\n    \u003ctd\u003e1.007\u003c/td\u003e\n  \u003c/tr\u003e\n  \u003ctr\u003e\n    \u003ctd\u003eV05\u003c/td\u003e\n    \u003ctd\u003eV4\u003c/td\u003e\n    \u003ctd\u003e活载荷\u003c/td\u003e\n    \u003ctd\u003e7.88\u003c/td\u003e\n    \u003ctd\u003e0.814\u003c/td\u003e\n  \u003c/tr\u003e\n  \u003ctr\u003e\n    \u003ctd\u003eV06\u003c/td\u003e\n    \u003ctd\u003eV5\u003c/td\u003e\n    \u003ctd\u003e活载荷\u003c/td\u003e\n    \u003ctd\u003e8.11\u003c/td\u003e\n    \u003ctd\u003e0.780\u003c/td\u003e\n  \u003c/tr\u003e\n  \u003ctr\u003e\n    \u003ctd\u003eV07\u003c/td\u003e\n    \u003ctd\u003eV6\u003c/td\u003e\n    \u003ctd\u003e活载荷\u003c/td\u003e\n    \u003ctd\u003e8.54\u003c/td\u003e\n    \u003ctd\u003e0.815\u003c/td\u003e\n  \u003c/tr\u003e\n  \u003ctr\u003e\n    \u003ctd\u003eV08\u003c/td\u003e\n    \u003ctd\u003eV7\u003c/td\u003e\n    \u003ctd\u003e活载荷\u003c/td\u003e\n    \u003ctd\u003e6.77\u003c/td\u003e\n    \u003ctd\u003e0.700\u003c/td\u003e\n  \u003c/tr\u003e\n  \u003ctr\u003e\n    \u003ctd\u003eV09\u003c/td\u003e\n    \u003ctd\u003eV8\u003c/td\u003e\n    \u003ctd\u003e活载荷\u003c/td\u003e\n    \u003ctd\u003e8.59\u003c/td\u003e\n    \u003ctd\u003e0.888\u003c/td\u003e\n  \u003c/tr\u003e\n  \u003ctr\u003e\n    \u003ctd\u003eL01\u003c/td\u003e\n    \u003ctd\u003eL1\u003c/td\u003e\n    \u003ctd\u003e活载荷\u003c/td\u003e\n    \u003ctd\u003e13.33\u003c/td\u003e\n    \u003ctd\u003e3.089\u003c/td\u003e\n  \u003c/tr\u003e\n  \u003ctr\u003e\n    \u003ctd\u003eL02\u003c/td\u003e\n    \u003ctd\u003eL2\u003c/td\u003e\n    \u003ctd\u003e活载荷\u003c/td\u003e\n    \u003ctd\u003e9.69\u003c/td\u003e\n    \u003ctd\u003e2.247\u003c/td\u003e\n  \u003c/tr\u003e\n  \u003ctr\u003e\n    \u003ctd\u003eL03\u003c/td\u003e\n    \u003ctd\u003eL3\u003c/td\u003e\n    \u003ctd\u003e\u003c/td\u003e\n    \u003ctd\u003e2.96\u003c/td\u003e\n    \u003ctd\u003e1.480\u003c/td\u003e\n  \u003c/tr\u003e\n  \u003ctr\u003e\n    \u003ctd\u003eL04\u003c/td\u003e\n    \u003ctd\u003eL4\u003c/td\u003e\n    \u003ctd\u003e\u003c/td\u003e\n    \u003ctd\u003e3.40\u003c/td\u003e\n    \u003ctd\u003e1.700\u003c/td\u003e\n  \u003c/tr\u003e\n  \u003ctr\u003e\n    \u003ctd\u003eL05\u003c/td\u003e\n    \u003ctd\u003eL5\u003c/td\u003e\n    \u003ctd\u003e\u003c/td\u003e\n    \u003ctd\u003e2.45\u003c/td\u003e\n    \u003ctd\u003e1.224\u003c/td\u003e\n  \u003c/tr\u003e\n  \u003ctr\u003e\n    \u003ctd\u003eL06\u003c/td\u003e\n    \u003ctd\u003eL6\u003c/td\u003e\n    \u003ctd\u003e\u003c/td\u003e\n    \u003ctd\u003e2.01\u003c/td\u003e\n    \u003ctd\u003e1.006\u003c/td\u003e\n  \u003c/tr\u003e\n  \u003ctr\u003e\n    \u003ctd\u003eL07\u003c/td\u003e\n    \u003ctd\u003eL7\u003c/td\u003e\n    \u003ctd\u003e\u003c/td\u003e\n    \u003ctd\u003e2.38\u003c/td\u003e\n    \u003ctd\u003e1.192\u003c/td\u003e\n  \u003c/tr\u003e\n  \u003ctr\u003e\n    \u003ctd\u003eL08\u003c/td\u003e\n    \u003ctd\u003eL8\u003c/td\u003e\n    \u003ctd\u003e\u003c/td\u003e\n    \u003ctd\u003e2.10\u003c/td\u003e\n    \u003ctd\u003e1.050\u003c/td\u003e\n  \u003c/tr\u003e\n  \u003ctr\u003e\n    \u003ctd\u003eT01\u003c/td\u003e\n    \u003ctd\u003eT1\u003c/td\u003e\n    \u003ctd\u003e活载荷\u003c/td\u003e\n    \u003ctd\u003e25.29\u003c/td\u003e\n    \u003ctd\u003e3.073\u003c/td\u003e\n  \u003c/tr\u003e\n  \u003ctr\u003e\n    \u003ctd\u003eT02\u003c/td\u003e\n    \u003ctd\u003eT2\u003c/td\u003e\n    \u003ctd\u003e活载荷\u003c/td\u003e\n    \u003ctd\u003e27.39\u003c/td\u003e\n    \u003ctd\u003e3.327\u003c/td\u003e\n  \u003c/tr\u003e\n  \u003ctr\u003e\n    \u003ctd\u003eT03\u003c/td\u003e\n    \u003ctd\u003eT3\u003c/td\u003e\n    \u003ctd\u003e活载荷\u003c/td\u003e\n    \u003ctd\u003e8.03\u003c/td\u003e\n    \u003ctd\u003e2.543\u003c/td\u003e\n  \u003c/tr\u003e\n  \u003ctr\u003e\n    \u003ctd\u003eT04\u003c/td\u003e\n    \u003ctd\u003eT4\u003c/td\u003e\n    \u003ctd\u003e活载荷\u003c/td\u003e\n    \u003ctd\u003e11.19\u003c/td\u003e\n    \u003ctd\u003e3.542\u003c/td\u003e\n  \u003c/tr\u003e\n  \u003ctr\u003e\n    \u003ctd\u003eT05\u003c/td\u003e\n    \u003ctd\u003eT5\u003c/td\u003e\n    \u003ctd\u003e活载荷\u003c/td\u003e\n    \u003ctd\u003e11.34\u003c/td\u003e\n    \u003ctd\u003e3.592\u003c/td\u003e\n  \u003c/tr\u003e\n  \u003ctr\u003e\n    \u003ctd\u003eT06\u003c/td\u003e\n    \u003ctd\u003eT6\u003c/td\u003e\n    \u003ctd\u003e活载荷\u003c/td\u003e\n    \u003ctd\u003e16.47\u003c/td\u003e\n    \u003ctd\u003e5.217\u003c/td\u003e\n  \u003c/tr\u003e\n  \u003ctr\u003e\n    \u003ctd\u003eT07\u003c/td\u003e\n    \u003ctd\u003eT7\u003c/td\u003e\n    \u003ctd\u003e活载荷\u003c/td\u003e\n    \u003ctd\u003e11.05\u003c/td\u003e\n    \u003ctd\u003e3.498\u003c/td\u003e\n  \u003c/tr\u003e\n  \u003ctr\u003e\n    \u003ctd\u003eT08\u003c/td\u003e\n    \u003ctd\u003eT8\u003c/td\u003e\n    \u003ctd\u003e活载荷\u003c/td\u003e\n    \u003ctd\u003e8.66\u003c/td\u003e\n    \u003ctd\u003e2.743\u003c/td\u003e\n  \u003c/tr\u003e\n  \u003ctr\u003e\n    \u003ctd\u003eT09\u003c/td\u003e\n    \u003ctd\u003eWT1\u003c/td\u003e\n    \u003ctd\u003e活载荷\u003c/td\u003e\n    \u003ctd\u003e36.56\u003c/td\u003e\n    \u003ctd\u003e2.365\u003c/td\u003e\n  \u003c/tr\u003e\n  \u003ctr\u003e\n    \u003ctd\u003eT10\u003c/td\u003e\n    \u003ctd\u003eWT2\u003c/td\u003e\n    \u003ctd\u003e活载荷\u003c/td\u003e\n    \u003ctd\u003e24.55\u003c/td\u003e\n    \u003ctd\u003e2.853\u003c/td\u003e\n  \u003c/tr\u003e\n  \u003ctr\u003e\n    \u003ctd\u003eT11\u003c/td\u003e\n    \u003ctd\u003eWT3\u003c/td\u003e\n    \u003ctd\u003e活载荷\u003c/td\u003e\n    \u003ctd\u003e38.06\u003c/td\u003e\n    \u003ctd\u003e4.784\u003c/td\u003e\n  \u003c/tr\u003e\n  \u003ctr\u003e\n    \u003ctd\u003eT12\u003c/td\u003e\n    \u003ctd\u003eWT4\u003c/td\u003e\n    \u003ctd\u003e活载荷\u003c/td\u003e\n    \u003ctd\u003e37.70\u003c/td\u003e\n    \u003ctd\u003e5.030\u003c/td\u003e\n  \u003c/tr\u003e\n  \u003ctr\u003e\n    \u003ctd\u003eT13\u003c/td\u003e\n    \u003ctd\u003eWT5\u003c/td\u003e\n    \u003ctd\u003e活载荷\u003c/td\u003e\n    \u003ctd\u003e30.48\u003c/td\u003e\n    \u003ctd\u003e4.524\u003c/td\u003e\n  \u003c/tr\u003e\n\u003c/table\u003e\n```\n````\n\n##### Document Parsing\n\nTo invoke this built-in task, set `Parameters.OcrOptions.Task` to `document_parsing`. No additional text information needs to be provided.\n\nThis task read images(usually scanned PDF) and return them in LaTeX format.\n\nExample:\n\n![](sample/Cnblogs.DashScope.Sample/scanned.jpg)\n\n```csharp\nawait using var file = File.OpenRead(\"scanned.jpg\");\nvar ossLink = await client.UploadTemporaryFileAsync(\"qwen-vl-ocr-latest\", file, \"scanned.jpg\");\nConsole.WriteLine($\"File uploaded: {ossLink}\");\nvar messages =\n    new List\u003cMultimodalMessage\u003e { MultimodalMessage.User([MultimodalMessageContent.ImageContent(ossLink)]) };\nvar completion = await client.GetMultimodalGenerationAsync(\n    new ModelRequest\u003cMultimodalInput, IMultimodalParameters\u003e()\n    {\n        Model = \"qwen-vl-ocr-latest\",\n        Input = new MultimodalInput { Messages = messages },\n        Parameters = new MultimodalParameters()\n        {\n            OcrOptions = new MultimodalOcrOptions()\n            {\n                Task = \"document_parsing\",\n            }\n        }\n    });\n```\n\nReturns:\n\n````markdown\n```latex\n\\section*{Qwen2-VL: Enhancing Vision-Language Model's Perception of the World at Any Resolution}\n\nPeng Wang* \\quad Shuai Bai* \\quad Sinan Tan* \\quad Shijie Wang* \\quad Zhihao Fan* \\quad Jinze Bai*? \\\\\nKeqin Chen \\quad Xuejing Liu \\quad Jialin Wang \\quad Wenbin Ge \\quad Yang Fan \\quad Kai Dang \\quad Mengfei Du \\\\\nXuancheng Ren \\quad Rui Men \\quad Dayiheng Liu \\quad Chang Zhou \\quad Jingren Zhou \\quad Junyang Lin*? \\\\\nQwen Team \\quad Alibaba Group\n\n\\begin{abstract}\nWe present the Qwen2-VL Series, an advanced upgrade of the previous Qwen-VL models that redefines the conventional predetermined-resolution approach in visual processing. Qwen2-VL introduces the Naive Dynamic Resolution mechanism, which enables the model to dynamically process images of varying resolutions into different numbers of visual tokens. This approach allows the model to generate more efficient and accurate visual representations, closely aligning with human perceptual processes. The model also integrates Multimodal Rotary Position Embedding (M-RoPE), facilitating the effective fusion of positional information across text, images, and videos. We employ a unified paradigm for processing both images and videos, enhancing the model's visual perception capabilities. To explore the potential of large multimodal models, Qwen2-VL investigates the scaling laws for large vision-language models (LVLMS). By scaling both the model size-with versions at 2B, 8B, and 72B parameters-and the amount of training data, the Qwen2-VL Series achieves highly competitive performance. Notably, the Qwen2-VL-72B model achieves results comparable to leading models such as GPT-4o and Claude3.5-Sonnet across various multimodal benchmarks, outperforming other generalist models. Code is available at \\url{https://github.com/QwenLM/Qwen2-VL}.\n\\end{abstract}\n\n\\section{Introduction}\n\nIn the realm of artificial intelligence, Large Vision-Language Models (LVLMS) represent a significant leap forward, building upon the strong textual processing capabilities of traditional large language models. These advanced models now encompass the ability to interpret and analyze a broader spectrum of data, including images, audio, and video. This expansion of capabilities has transformed LVLMS into indispensable tools for tackling a variety of real-world challenges. Recognized for their unique capacity to condense extensive and intricate knowledge into functional representations, LVLMS are paving the way for more comprehensive cognitive systems. By integrating diverse data forms, LVLMS aim to more closely mimic the nuanced ways in which humans perceive and interact with their environment. This allows these models to provide a more accurate representation of how we engage with and perceive our environment.\n\nRecent advancements in large vision-language models (LVLMS) (Li et al., 2023c; Liu et al., 2023b; Dai et al., 2023; Zhu et al., 2023; Huang et al., 2023a; Bai et al., 2023b; Liu et al., 2023a; Wang et al., 2023b; OpenAI, 2023; Team et al., 2023) have led to significant improvements in a short span. These models (OpenAI, 2023; Touvron et al., 2023a,b; Chiang et al., 2023; Bai et al., 2023a) generally follow a common approach of \\textit{visual encoder} $\\rightarrow$ \\textit{cross-modal connector} $\\rightarrow$ \\textit{LLM}. This setup, combined with next-token prediction as the primary training method and the availability of high-quality datasets (Liu et al., 2023a; Zhang et al., 2023; Chen et al., 2023b);\n\n*Equal core contribution, ?Corresponding author\n\n```\n````\n\n##### Formula Recognition\n\nTo invoke this built-in task, set `Parameters.OcrOptions.Task` to `formula_recognition`. No additional text information needs to be provided.\n\nThis task read images(like handwriting formulas) and return them in LaTeX format.\n\nExample:\n\n![](sample/Cnblogs.DashScope.Sample/math.jpg)\n\n```csharp\n// upload file\nawait using var file = File.OpenRead(\"math.jpg\");\nvar ossLink = await client.UploadTemporaryFileAsync(\"qwen-vl-ocr-latest\", file, \"math.jpg\");\nConsole.WriteLine($\"File uploaded: {ossLink}\");\nvar messages =\n    new List\u003cMultimodalMessage\u003e { MultimodalMessage.User([MultimodalMessageContent.ImageContent(ossLink)]) };\nvar completion = await client.GetMultimodalGenerationAsync(\n    new ModelRequest\u003cMultimodalInput, IMultimodalParameters\u003e()\n    {\n        Model = \"qwen-vl-ocr-latest\",\n        Input = new MultimodalInput { Messages = messages },\n        Parameters = new MultimodalParameters()\n        {\n            OcrOptions = new MultimodalOcrOptions()\n            {\n                Task = \"formula_recognition\",\n            }\n        }\n    });\n\nConsole.WriteLine(\"LaTeX:\");\nConsole.WriteLine(completion.Output.Choices[0].Message.Content[0].Text);\n\nif (completion.Usage != null)\n{\n    var usage = completion.Usage;\n    Console.WriteLine(\n        $\"Usage: in({usage.InputTokens})/out({usage.OutputTokens})/image({usage.ImageTokens})/total({usage.TotalTokens})\");\n}\n```\n\nReturns:\n\n````markdown\n```latex\n\\begin{align*}\n\\tilde{G}(x) \u0026= \\frac{\\alpha}{\\kappa}x, \\quad \\tilde{T}_i = T, \\quad \\tilde{H}_i = \\tilde{\\kappa}T, \\quad \\tilde{\\lambda}_i = \\frac{1}{\\kappa}\\sum_{j=1}^{m}\\omega_j - z_i, \\\\\nL(\\{p_n\\}; m^n) + L(\\{x^n\\}, m^n) + L(\\{m^n\\}; q_n) \u0026= L(m^n; q_n) \\\\\nI^{m_n} - (L+1) \u0026= z + \\int_0^1 I^{m_n} - (L)z \\leq x_m | L^{m_n} - (L) |^3 \\\\\n\u0026\\leq \\kappa\\partial_1\\psi(x) + \\frac{\\kappa^3}{6}\\partial_2^3\\psi(x) - V(x) \\psi(x) = \\int d^3y K(x,y) \\psi(y), \\\\\n\\int_{B_{\\kappa}(0)} I^{m}(w)^2 d\\gamma \u0026= \\lim_{n\\to\\infty} \\int_{B_{\\kappa}(0)} r\\psi(w_n)^2 d\\gamma = \\lim_{n\\to\\infty} \\int_{B_{\\kappa}(y_n)} d\\gamma \\geq \\beta \u003e 0,\n\\end{align*}\n```\n````\n\n$$\n\\begin{align*}\n\\tilde{G}(x) \u0026= \\frac{\\alpha}{\\kappa}x, \\quad \\tilde{T}_i = T, \\quad \\tilde{H}_i = \\tilde{\\kappa}T, \\quad \\tilde{\\lambda}_i = \\frac{1}{\\kappa}\\sum_{j=1}^{m}\\omega_j - z_i, \\\\\nL(\\{p_n\\}; m^n) + L(\\{x^n\\}, m^n) + L(\\{m^n\\}; q_n) \u0026= L(m^n; q_n) \\\\\nI^{m_n} - (L+1) \u0026= z + \\int_0^1 I^{m_n} - (L)z \\leq x_m | L^{m_n} - (L) |^3 \\\\\n\u0026\\leq \\kappa\\partial_1\\psi(x) + \\frac{\\kappa^3}{6}\\partial_2^3\\psi(x) - V(x) \\psi(x) = \\int d^3y K(x,y) \\psi(y), \\\\\n\\int_{B_{\\kappa}(0)} I^{m}(w)^2 d\\gamma \u0026= \\lim_{n\\to\\infty} \\int_{B_{\\kappa}(0)} r\\psi(w_n)^2 d\\gamma = \\lim_{n\\to\\infty} \\int_{B_{\\kappa}(y_n)} d\\gamma \\geq \\beta \u003e 0,\n\\end{align*}\n$$\n\n\n\n##### Text Recognition\n\nTo invoke this built-in task, set `Parameters.OcrOptions.Task` to `text_recognition`. No additional text information needs to be provided.\n\nThis task read the images and returns content in plain text(Chinese and English only).\n\nExample:\n\n![](sample/Cnblogs.DashScope.Sample/webpage.jpg)\n\n```csharp\n// upload file\nawait using var file = File.OpenRead(\"webpage.jpg\");\nvar ossLink = await client.UploadTemporaryFileAsync(\"qwen-vl-ocr-latest\", file, \"webpage.jpg\");\nConsole.WriteLine($\"File uploaded: {ossLink}\");\nvar messages =\n    new List\u003cMultimodalMessage\u003e { MultimodalMessage.User([MultimodalMessageContent.ImageContent(ossLink)]) };\nvar completion = await client.GetMultimodalGenerationAsync(\n    new ModelRequest\u003cMultimodalInput, IMultimodalParameters\u003e()\n    {\n        Model = \"qwen-vl-ocr-latest\",\n        Input = new MultimodalInput { Messages = messages },\n        Parameters = new MultimodalParameters()\n        {\n            OcrOptions = new MultimodalOcrOptions()\n            {\n                Task = \"text_recognition\",\n            }\n        }\n    });\n```\n\nReturns\n\n```plaintext\nOpenAI 兼容 DashScope\nPython Java curl\n```\n\n##### Multilanguage\n\nTo invoke this built-in task, set `Parameters.OcrOptions.Task` to `multi_lan`. No additional text information needs to be provided.\n\nThis task read the images and returns content in plain text(Support more languages).\n\n![](sample/Cnblogs.DashScope.Sample/multilanguage.jpg)\n\n```csharp\nawait using var file = File.OpenRead(\"multilanguage.jpg\");\nvar ossLink = await client.UploadTemporaryFileAsync(\"qwen-vl-ocr-latest\", file, \"multilanguage.jpg\");\nConsole.WriteLine($\"File uploaded: {ossLink}\");\nvar messages =\n    new List\u003cMultimodalMessage\u003e { MultimodalMessage.User([MultimodalMessageContent.ImageContent(ossLink)]) };\nvar completion = await client.GetMultimodalGenerationAsync(\n    new ModelRequest\u003cMultimodalInput, IMultimodalParameters\u003e()\n    {\n        Model = \"qwen-vl-ocr-latest\",\n        Input = new MultimodalInput { Messages = messages },\n        Parameters = new MultimodalParameters()\n        {\n            OcrOptions = new MultimodalOcrOptions()\n            {\n                Task = \"multi_lan\",\n            }\n        }\n    });\n```\n\nReturns\n\n```csharp\nINTERNATIONAL\nMOTHER LANGUAGE\nDAY\n你好!\nПрив?т!\nBonjour!\nMerhaba!\nCiao!\nHello!\nOla!\n????\nSalam!\n```\n\n### GUI\n\nUse `gui-plus` to generate standardized operational information based on screenshots and user intent.\n\nCurrently, the main capabilities are implemented through the `System Prompt`, where you can configure the model’s available capabilities and the output JSON format.\n\nSample system prompt:\n\n```markdown\n## 1. Core Role\nYou are an expert AI Vision Operation Agent. Your task is to analyze computer screenshots, understand user instructions, and then break down the task into single, precise GUI atomic operations.\n## 2. [CRITICAL] JSON Schema \u0026 Absolute Rules\nYour output **must** be a JSON object that strictly adheres to the following rules. **Any deviation will result in failure**.\n- **[R1] Strict JSON**: Your response **must** be *and only be* a JSON object. Do not add any text, comments, or explanations before or after the JSON code block.\n- **[R2] Strict `thought` Structure**: The `thought` object must contain a single sentence briefly describing your thought process. For example: \"The user wants to open the browser. I see the Chrome icon on the desktop, so the next step is to click it.\"\n- **[R3] Precise `action` Value**: The value of the `action` field **must** be an uppercase string defined in `## 3. Toolset` (e.g., `\"CLICK\"`, `\"TYPE\"`). No leading/trailing spaces or case variations are allowed.\n- **[R4] Strict `parameters` Structure**: The structure of the `parameters` object **must** be **perfectly identical** to the template defined for the selected Action in `## 3. Toolset`. Key names and value types must match exactly.\n## 3. Toolset (Available Actions)\n### CLICK\n- **Description**: Click on the screen.\n- **Parameters Template**:\n  {\n    \"x\": \u003cinteger\u003e,\n    \"y\": \u003cinteger\u003e,\n    \"description\": \"\u003cstring, optional: A short string describing what you are clicking on, e.g., 'Chrome browser icon' or 'Login button'.\u003e\"\n  }\n\n### TYPE\n- **Description**: Type text.\n- **Parameters Template**:\n{\n  \"text\": \"\u003cstring\u003e\",\n  \"needs_enter\": \u003cboolean\u003e\n}\n\n### SCROLL\n- **Description**: Scroll the window.\n- **Parameters Template**:\n{\n  \"direction\": \"\u003c'up' or 'down'\u003e\",\n  \"amount\": \"\u003c'small', 'medium', or 'large'\u003e\"\n}\n\n### KEY_PRESS\n- **Description**: Press a function key.\n- **Parameters Template**:\n{\n  \"key\": \"\u003cstring: e.g., 'enter', 'esc', 'alt+f4'\u003e\"\n}\n\n### FINISH\n- **Description**: Task completed successfully.\n- **Parameters Template**:\n{\n  \"message\": \"\u003cstring: A summary of the task completion\u003e\"\n}\n\n### FAILE\n- **Description**: Task cannot be completed.\n- **Parameters Template**:\n{\n  \"reason\": \"\u003cstring: A clear explanation of the failure reason\u003e\"\n}\n\n## 4. Thinking and Decision Framework\nBefore generating each action, strictly follow the following thought-verification process:\n**Goal Analysis**: What is the user's ultimate goal?\n**Screen Observation (Grounded Observation)**: Carefully analyze the screenshot. Your decisions must be based on visual evidence present in the screenshot. If you cannot see an element, you cannot interact with it.\n**Action Decision**: Based on the goal and visible elements, select the most appropriate tool.\n**Construct Output**:\na. Record your thought process in the `thought` field.\nb. Select an `action`.\nc. Precisely copy the `parameters` template for that action and fill in the values.\n**Final Verification (Self-Correction)**: Before outputting, perform a final check:\n- Is my response pure JSON?\n- Is the `action` value correct (uppercase, no spaces)?\n- Is the `parameters` structure 100% identical to the template? For example, for `CLICK`, are there separate `x` and `y` keys, and are their values integers?\n```\n\nRequest:\n\n```csharp\nvar messages = new List\u003cMultimodalMessage\u003e\n{\n    MultimodalMessage.System([MultimodalMessageContent.TextContent(SystemPrompt)]),\n    MultimodalMessage.User(\n    [\n        MultimodalMessageContent.ImageContent(\n            \"https://img.alicdn.com/imgextra/i2/O1CN016iJ8ob1C3xP1s2M6z_!!6000000000026-2-tps-3008-1758.png\"),\n        MultimodalMessageContent.TextContent(\"Open browser\")\n    ])\n};\nvar completion = client.GetMultimodalGenerationStreamAsync(\n    new ModelRequest\u003cMultimodalInput, IMultimodalParameters\u003e()\n    {\n        Model = \"gui-plus\",\n        Input = new MultimodalInput() { Messages = messages },\n        Parameters = new MultimodalParameters() { IncrementalOutput = true, }\n    });\n```\n\nResponse:\n\n```csharp\n{\n  \"thought\": \"用户想打开浏览器，我看到了桌面上的Google Chrome图标，因此下一步是点击它。\",\n  \"action\": \"CLICK\",\n  \"parameters\": {\n    \"x\": 1089,\n    \"y\": 123\n  }\n}\n```\n\nThen you can execute the command that model returns, and reply the screenshot with next intension.\n\n### Audio Understanding\n\nExample(use `Qwen3-Omni-Captioner`)\n\n```csharp\n// upload file\nawait using var audio = File.OpenRead(\"noise.wav\");\nvar ossLink = await client.UploadTemporaryFileAsync(\"qwen3-omni-30b-a3b-captioner\", audio, \"noise.wav\");\nConsole.WriteLine($\"File uploaded: {ossLink}\");\nvar messages = new List\u003cMultimodalMessage\u003e\n{\n    MultimodalMessage.User(\n    [\n        // 也可以直接传入公网地址\n        MultimodalMessageContent.AudioContent(ossLink),\n    ])\n};\nvar completion = client.GetMultimodalGenerationStreamAsync(\n    new ModelRequest\u003cMultimodalInput, IMultimodalParameters\u003e()\n    {\n        Model = \"qwen3-omni-30b-a3b-captioner\",\n        Input = new MultimodalInput() { Messages = messages },\n        Parameters = new MultimodalParameters() { IncrementalOutput = true, }\n    });\nvar reply = new StringBuilder();\nvar first = true;\nMultimodalTokenUsage? usage = null;\nawait foreach (var chunk in completion)\n{\n    var choice = chunk.Output.Choices[0];\n    if (first)\n    {\n        first = false;\n        Console.WriteLine();\n        Console.Write(\"Assistant \u003e \");\n    }\n\n    if (choice.Message.Content.Count == 0)\n    {\n        continue;\n    }\n\n    Console.Write(choice.Message.Content[0].Text);\n    reply.Append(choice.Message.Content[0].Text);\n    usage = chunk.Usage;\n}\n\nConsole.WriteLine();\nmessages.Add(MultimodalMessage.Assistant([MultimodalMessageContent.TextContent(reply.ToString())]));\nif (usage != null)\n{\n    Console.WriteLine(\n        $\"Usage: in({usage.InputTokens})/out({usage.OutputTokens})/audio({usage.InputTokensDetails?.AudioTokens})/total({usage.TotalTokens})\");\n}\n```\n\nSample output\n\n```csharp\nAssistant \u003e The audio clip opens with a rapid, percussive metallic clatter, reminiscent of a typewriter or similar mechanical device, which continues in a steady rhythm throughout the recording. This clatter is slightly left-of-center in the stereo field and is accompanied by a faint, low-frequency hum, likely from a household appliance or HVAC system. The acoustic environment is a small, enclosed room with hard surfaces, indicated by the short, bright reverberation of both the clatter and the speaker’s voice. The audio quality is moderate, with a noticeable electronic hiss and some loss of high-frequency detail, but no digital distortion or clipping.\n\nAt the one-second mark, a male voice enters, positioned slightly right-of-center and closer to the microphone. He speaks in standard Mandarin, with a tone of weary exasperation: “哎 呀，这样我还怎么安静工作啊？” (“Aiyā, zěnyàng wǒ hái zěnme ānjìng gōngzuò a?”), which translates to “Oh, how can I possibly work quietly like this?” His speech is clear, with a slightly rising pitch on “安静” (“quietly”) and a falling pitch on “啊” (“a”), conveying a sense of complaint and fatigue. The accent is standard, with no regional inflection, and the voice is that of a young to middle-aged adult male.\n\nThroughout the clip, the mechanical clatter remains constant and prominent, occasionally competing with the voice for clarity. There are no other sounds, such as footsteps, additional voices, or environmental noises, and the background is otherwise quiet. The interplay between the persistent mechanical noise and the speaker’s complaint creates a vivid sense of disruption and frustration, suggesting an environment where work is being impeded by an external, uncontrolled sound source.\n\nCulturally, the use of Mandarin, standard pronunciation, and modern recording quality indicate a contemporary, urban Chinese setting. The language and tone are universally relatable, reflecting a common experience of being disturbed during work. The lack of regional markers or distinctive background noises suggests a generic, possibly domestic or office-like space, but with no clear indicators of a specific location or social context.\n\nIn summary, the audio portrays a modern Mandarin-speaking man, exasperated by a constant, distracting mechanical noise (likely a typewriter or similar device), attempting to work in a small, reverberant room. The recording’s technical and acoustic features reinforce the sense of disruption and frustration, while the language and setting suggest a contemporary, urban Chinese context.\nUsage: in(160)/out(514)/audio(152)/total(674)\n```\n\n## Text-to-Speech\n\nCreate a speech synthesis session using `dashScopeClient.CreateSpeechSynthesizerSocketSessionAsync()`.\n\nNote: Use the using statement to automatically dispose the session, or manually call Dispose() to release resources. Avoid reusing sessions.\n\nCreate a synthesis session:\n```csharp\nusing var tts = await dashScopeClient.CreateSpeechSynthesizerSocketSessionAsync(\"cosyvoice-v2\");\nvar taskId = await tts.RunTaskAsync(new SpeechSynthesizerParameters { Voice = \"longxiaochun_v2\", Format = \"mp3\" });\nawait tts.ContinueTaskAsync(taskId, \"Cnblogs\");\nawait tts.ContinueTaskAsync(taskId, \"Code changes the world\");\nawait tts.FinishTaskAsync(taskId);\nvar file = new FileInfo(\"tts.mp3\");\nusing var stream = file.OpenWrite();\nawait foreach (var b in tts.GetAudioAsync())\n{\n    stream.WriteByte(b);\n}\nConsole.WriteLine($\"Audio saved to {file.FullName}\");\n```\n## Image Generation\n### Text-to-Image\nUse shortcuts for Wanx models:\n```csharp\nvar task = await dashScopeClient.CreateWanxImageSynthesisTaskAsync(\n    WanxModel.WanxV21Turbo,\n    \"A futuristic cityscape at sunset\",\n    new ImageSynthesisParameters { Style = ImageStyles.OilPainting });\n// Pull status\nwhile (true)\n{\n    var result = await dashScopeClient.GetWanxImageSynthesisTaskAsync(task.TaskId);\n    if (result.Output.TaskStatus == DashScopeTaskStatus.Succeeded)\n    {\n        Console.WriteLine($\"Image URL: {result.Output.Results[0].Url}\");\n        break;\n    }\n    await Task.Delay(500);\n}\n```\n#### Portrait Style Transfer\nUse `CreateWanxImageGenerationTaskAsync` and `GetWanxImageGenerationTaskAsync`\n\n#### Background Generation\n\nUse `CreateWanxBackgroundGenerationTaskAsync` and `GetWanxBackgroundGenerationTaskAsync`\n\n## Application Call\n```csharp\nvar request =\n    new ApplicationRequest()\n    {\n        Input = new ApplicationInput() { Prompt = \"Summarize this file.\" },\n        Parameters = new ApplicationParameters()\n        {\n            TopK = 100,\n            TopP = 0.8f,\n            Seed = 1234,\n            Temperature = 0.85f,\n            RagOptions = new ApplicationRagOptions()\n            {\n                PipelineIds = [\"thie5bysoj\"],\n                FileIds = [\"file_d129d632800c45aa9e7421b30561f447_10207234\"]\n            }\n        }\n    };\nvar response = await client.GetApplicationResponseAsync(\"your-application-id\", request);\nConsole.WriteLine(response.Output.Text);\n```\n`ApplicationRequest` uses `Dictionary\u003cstring, object?\u003e` as the default type for `BizParams`.\n\n```csharp\nvar request =\n    new ApplicationRequest()\n    {\n        Input = new ApplicationInput()\n        {\n            Prompt = \"Summarize this file.\",\n            BizParams = new Dictionary\u003cstring, object?\u003e()\n            {\n                { \"customKey1\", \"custom-value\" }\n            }\n        }\n    };\nvar response = await client.GetApplicationResponseAsync(\"your-application-id\", request);\nConsole.WriteLine(response.Output.Text);\n```\nFor strong typing support, you can use the generic class `ApplicationRequest\u003cTBizParams\u003e`.\nNote that the SDK uses `snake_case` for JSON serialization. If your application uses different naming conventions, manually specify the serialized property names using `[JsonPropertyName(\"camelCase\")]`.\n\n```csharp\npublic record TestApplicationBizParam(\n    [property: JsonPropertyName(\"sourceCode\")]\n    string SourceCode);\nvar request =\n    new ApplicationRequest\u003cTestApplicationBizParam\u003e()\n    {\n        Input = new ApplicationInput\u003cTestApplicationBizParam\u003e()\n        {\n            Prompt = \"Summarize this file.\",\n            BizParams = new TestApplicationBizParam(\"test\")\n        }\n    };\nvar response = await client.GetApplicationResponseAsync(\"your-application-id\", request);\nConsole.WriteLine(response.Output.Text);\n```\n\n## Batch\n\nUse `OpenAiCompatibleUploadFileAsync`, `OpenAiCompatibleCreateBatchAsync`, `OpenAiCompatibleGetBatchAsync`, `OpenAiCompatibleListBatchesAsync`, and `OpenAiCompatibleCancelBatchAsync` to manage batch jobs.\n\nBatch API allows you to submit multiple requests in a single JSONL file for asynchronous processing, which is useful for large-scale tasks.\n\n### Upload File and Create Batch Job\n\n```csharp\nvar client = new DashScopeClient(\"your-api-key\");\n\n// Prepare JSONL content\nvar jsonl =\n    \"\"\"\n    {\"custom_id\":\"1\",\"method\":\"POST\",\"url\":\"/v1/chat/ds-test\",\"body\":{\"model\":\"batch-test-model\",\"messages\":[{\"role\":\"system\",\"content\":\"You are a helpful assistant.\"},{\"role\":\"user\",\"content\":\"你好！有什么可以帮助你的吗？\"}]}}\n    {\"custom_id\":\"2\",\"method\":\"POST\",\"url\":\"/v1/chat/ds-test\",\"body\":{\"model\":\"batch-test-model\",\"messages\":[{\"role\":\"system\",\"content\":\"You are a helpful assistant.\"},{\"role\":\"user\",\"content\":\"What is 2+2?\"}]}}\n    \"\"\";\nusing var stream = new MemoryStream(Encoding.UTF8.GetBytes(jsonl));\n\n// Upload file with purpose \"batch\"\nvar inputFile = await client.OpenAiCompatibleUploadFileAsync(stream, \"batch_input.jsonl\", \"batch\");\n\n// Create batch job\nvar batch = await client.OpenAiCompatibleCreateBatchAsync(new DashScopeCreateBatchRequest()\n{\n    InputFileId = inputFile.Id.Value,\n    CompletionWindow = \"24h\", // Supports \"h\" (hours) and \"d\" (days), range: 24h to 336h\n    Endpoint = \"/v1/chat/ds-test\",\n    Metadata = new DashScopeBatchMetadata()\n    {\n        DsName = \"My Batch Job\",           // Optional, max 100 characters\n        DsDescription = \"Description\",      // Optional, max 200 characters\n        DsBatchFinishCallback = \"https://example.com/callback\" // Optional callback URL\n    }\n});\n```\n\n### Poll for Completion and Get Results\n\n```csharp\n// Poll batch status\nbatch = await client.OpenAiCompatibleGetBatchAsync(batch.Id);\n\n// When completed, download the output file\nif (batch.Status == \"completed\" \u0026\u0026 batch.OutputFileId != null)\n{\n    await using var result = await client.OpenAiCompatibleGetFileContentAsync(batch.OutputFileId);\n    using var streamReader = new StreamReader(result);\n    var content = await streamReader.ReadToEndAsync();\n    // or save to a jsonl file\n    // using var fileStream = new FileStream($\"{batch.OutputFileId}.jsonl\", FileMode.Create, FileAccess.Write, FileShare.None, 4096, true);\n    // await result.CopyToAsync(fileStream);\n}\n```\n\n### List and Cancel Batches\n\n```csharp\n// List batches with optional filters\nvar batches = await client.OpenAiCompatibleListBatchesAsync(\n    limit: 20,\n    dsName: \"keyword\"); // Search by name\n\n// Cancel a batch\nvar cancelled = await client.OpenAiCompatibleCancelBatchAsync(batchId);\n```\n\n### Cleanup\n\n```csharp\n// Delete uploaded files when no longer needed\nvar deletion = await client.OpenAiCompatibleDeleteFileAsync(fileId);\nConsole.WriteLine(deletion.Deleted ? $\"Deleted: {deletion.Id}\" : $\"Deletion failed: {deletion.Id}\");\n```\n\n## Text Embeddings\n\n```csharp\nvar text = \"Sample text for embedding\";\nvar response = await dashScopeClient.GetTextEmbeddingsAsync(\n    TextEmbeddingModel.TextEmbeddingV4,\n    [text],\n    new TextEmbeddingParameters { Dimension = 512 });\nvar embedding = response.Output.Embeddings.First().Embedding;\nConsole.WriteLine($\"Embedding vector length: {embedding.Length}\");\n```\n\nSee [Snapshot Files](./test/Cnblogs.DashScope.Tests.Shared/Utils/Snapshots.cs) for API parameter examples.\n\nReview [Tests](./test) for comprehensive usage examples.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcnblogs%2Fdashscope-sdk","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fcnblogs%2Fdashscope-sdk","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcnblogs%2Fdashscope-sdk/lists"}