
# 前缀续写
在日常的文本处理任务中，如撰写文章、构建聊天机器人的回复等，可能会遇到需要根据已有的文本片段生成后续内容的需求。然而，手动完成这些任务不仅耗时，而且效率低下。如何确保生成的后续内容既符合语义又高效呢？MaaS支持模型前缀续写能力。用户给定一段文本的前缀（即开头部分），大模型即可按照用户要求生成语义连贯、合理的后续文本内容。
#### 应用场景
前缀续写可以应用于多种场景，例如：
- 代码补全：在编程环境中，根据已有的代码片段预测并生成后续的代码。
- 自动写作：帮助作者完成文章、故事或诗歌的创作。
- 聊天机器人：根据用户的输入生成合适的回复。
- 邮件自动回复：根据邮件的开头部分自动生成回复内容。
#### 使用方法
目前MaaS的API V2和OpenAI兼容接口支持前缀续写，需在messages数组中将最后一条消息的"role"设置为"assistant"，并在其"content"中提供前缀。如果为V2接口，在消息中设置参数"prefix": true；如果为OpenAI兼容接口则需要在请求体中新增两个参数：①"continue_final_message":true；②"add_generation_prompt":false。请求体格式如下：
API V2：
```
{
  "model": "deepseek-v4-flash",
  "messages": [
    {
      "role": "user",
      "content": "基于Python语言实现数组快速排序，请勿添加其他内容"
    },
    {
      "role": "assistant",
      "content": "def quick_sort(array)",
      "prefix": true
    }
  ],
  "temperature": 0.6,
  "stream": false
}
```
OpenAI兼容接口：
```
{ 
    "model": "deepseek-v4-flash",
    "continue_final_message": true,
    "add_generation_prompt": false,
    "messages": [
        {"role": "user", "content": "你是一个计算器，请计算： 1 + 1 "},
        {"role": "assistant", "content": "="}
    ],
    "temperature": 0.6,
    "stream": false
}
```
模型会以前缀内容为起点开始生成。
#### 支持模型
当前支持前缀续写的模型请参见[文本生成](https://support.huaweicloud.com/model-list-maas/model_list_0001.html#section1)的支持能力。
#### API说明
关于API参数说明，请参见[MaaS标准API V2](https://support.huaweicloud.com/model-call-maas/model-call-019.html)或[OpenAI兼容接口](https://support.huaweicloud.com/model-call-maas/model-call-021.html)。
#### 模式对比
以deepseek-v4-flash为例：
表1普通模式与前缀续写模式对比 
| 对比项  | 普通模式                                                                                                                                                                                                                                                                                                                             | 前缀续写模式                                                                                                                                                                                                                                                                                                                                                 |
|:---|:---|:---|
| 请求示例 | ``` { "model": "deepseek-v4-flash", "messages": [ { "content": "你是一个聊天小助手", "role": "system" }, { "role": "user", "content": "写一个Python的快速排序函数，勿添加其它内容" } ], "temperature": 0.6, "stream": false } ```                                                                                                                           | ``` { "model": "deepseek-v4-flash", "messages": [ { "role": "user", "content": "基于Python语言实现数组快速排序，请勿添加其他内容" }, { "role": "assistant", "content": "def quick_sort(array)", "prefix": true } ], "temperature": 0.6, "stream": false } ```                                                                                                               |
| 返回示例 | 模型将根据问题生成完整的自然语言回复。 ``` def quick_sort(arr): if len(arr) <= 1: return arr pivot = arr[len(arr) // 2] left = [x for x in arr if x < pivot] middle = [x for x in arr if x == pivot] right = [x for x in arr if x > pivot] return quick_sort(left) + middle + quick_sort(right) ``` | 模型会以前缀内容（def quick_sort(array)）为起点开始生成。 ``` -> list: if len(array) <= 1: return array pivot = array[len(array) // 2] left = [x for x in array if x < pivot] middle = [x for x in array if x == pivot] right = [x for x in array if x > pivot] return quick_sort(left) + middle + quick_sort(right) ``` |
   
#### 前提条件
- 已在"模型推理 \> 在线推理 \> 预置服务"页签开通预置服务。详情请见[开通MaaS预置服务](https://support.huaweicloud.com/model-call-maas/model-call-052.html)。
- （可选）如果需要控制服务调用流量，可提前创建自定义接入点，详情请参见[创建自定义接入点](https://support.huaweicloud.com/model-call-maas/model-call-048.html#ZH-CN_TOPIC_0000002549717747__zh-cn_topic_0000002397381901_section446813817237)。

- 已获取API Key。详情请见[在MaaS管理API Key](https://support.huaweicloud.com/model-call-maas/model-call-049.html)。
- 已获取模型服务的model参数值。支持的模型信息和接口详情请见[对话Chat/Post](https://support.huaweicloud.com/model-call-maas/model-call-018.html)。
 
#### 快速开始
代码补全是前缀续写的核心应用场景。以下示例演示如何使用deepseek-v4-flash模型补全一个Python函数。
- [Python]
  ```
  import requests
  import json
  if __name__ == '__main__':
      url = "https://api.modelarts-maas.com/v2/chat/completions"  # API地址
      api_key = "MAAS_API_KEY"  # 把MAAS_API_KEY替换成已获取的API Key
      # Send request.
      headers = {
          'Content-Type': 'application/json',
          'Authorization': f'Bearer {api_key}'
      }
      data = {
          "model": "deepseek-v4-flash",
          "messages" : [{
              "role" : "user",
              "content" : "基于Python语言实现数组快速排序，请勿添加其他内容"}, 
        {
         "role" : "assistant",
         "content" : "def quick_sort(array)",
         "prefix" : True}],
        "temperature": 0.6,
        "stream": False
      }
      response = requests.post(url, headers=headers, data=json.dumps(data), verify=False)
      with open('response.txt', 'w', encoding='utf-8') as f:
          f.write(f"Status Code: {response.status_code}\n")
          f.write("Response Content:\n")
          f.write(response.text)
      # Print result.
      print(response.status_code)
      print(response.text)
  ```
  返回结果：
  ```
  if len(array) <= 1:
      return array
  pivot = array[len(array) // 2]
  left = [x for x in array if x < pivot]
  middle = [x for x in array if x == pivot]
  right = [x for x in array if x > pivot]
  return quick_sort(left) + middle + quick_sort(right)
  ```
- [Curl]
  ```
  curl -X POST "https://api.modelarts-maas.com/v2/chat/completions" \
    -H "Content-Type: application/json" \
    -H "Authorization: Bearer $MAAS_API_KEY" \
    -d '{
   "model": "deepseek-v4-flash",
   "messages":  [{
           "role": "user", "content": "基于Python语言实现数组快速排序，请勿添加其他内容"
      },
      {
        "role": "assistant","content": "def quick_sort(array)","prefix": true
      }],
      "temperature": 0.6,
   "stream": false
    }'
  ```
  返回结果：
  ```
  if len(array) <= 1:
   return array
  pivot = array[len(array) // 2]
  left = [x for x in array if x < pivot]
  middle = [x for x in array if x == pivot]
  right = [x for x in array if x > pivot]
  return quick_sort(left) + middle + quick_sort(right)
  ```
- [Java]
  建议JDK版本为15+。
  ```
  import java.io.IOException;
  import java.net.URI;
  import java.net.http.HttpClient;
  import java.net.http.HttpRequest;
  import java.net.http.HttpResponse;
  import java.nio.file.Files;
  import java.nio.file.Paths;
  import java.time.Duration;
  /**
   * 前缀续写
   * */
  public class ChatCompletionsClient {
      public static void main(String[] args) {
          // API 地址
          String url = "https://api.modelarts-maas.com/v2/chat/completions";
          // 请替换为真实 API Key
          String apiKey = "MAAS_API_KEY";
          // 可替换为支持前缀续写能力的模型
          String modelName = "deepseek-v4-flash"; 
          String jsonBody = String.format(
                  """
                          {
                              "model": "%s",
                              "messages": [
                                  {"role": "user", "content": "基于Python语言实现数组快速排序，请勿添加其他内容"},
                                  {"role": "assistant", "content": "def quick_sort(array)", "prefix" : true}
                              ],
                              "temperature": 0.6,
                              "stream": false
                          }""", modelName);
          try {
              HttpClient client = HttpClient.newBuilder()
                      .connectTimeout(Duration.ofSeconds(10))
                      .build();
              // 构建 HTTP 请求
              HttpRequest request = HttpRequest.newBuilder()
                      .uri(URI.create(url))
                      .header("Content-Type", "application/json")
                      .header("Authorization", "Bearer " + apiKey)
                      .POST(HttpRequest.BodyPublishers.ofString(jsonBody))
                      .build();
              // 发送请求并获取响应
              HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
              int statusCode = response.statusCode();
              String responseBody = response.body();
              // 将响应写入文件
              String fileContent = "Status Code: " + statusCode + "\nResponse Content:\n" + responseBody;
              Files.writeString(Paths.get("response.txt"), fileContent);
              // 控制台输出
              System.out.println(statusCode);
              System.out.println(responseBody);
          } catch (IOException | InterruptedException e) {
              e.printStackTrace();
          }
      }
  }
  ```
  返回结果：
  ```
  if len(array) <= 1:
   return array
  pivot = array[len(array) // 2]
  left = [x for x in array if x < pivot]
  middle = [x for x in array if x == pivot]
  right = [x for x in array if x > pivot]
  return quick_sort(left) + middle + quick_sort(right)
  ```
#### 场景一：角色扮演
在角色扮演场景中，用户希望生成的对话符合特定角色的人设要求，可通过前缀续写模型能力生成角色对话，使扮演角色符合角色人设条件。以下为Python示例代码，可通过model参数替换模型，model参数详情请参见[文本生成](https://support.huaweicloud.com/model-list-maas/model_list_0001.html#section1)。
- [MaaS标准API V2]
  ```
  #Python
  import requests
  import json
  if __name__ == '__main__':
      url = "https://api.modelarts-maas.com/v2/chat/completions"  # API地址
      api_key = "MAAS_API_KEY"  # 把MAAS_API_KEY替换成已获取的API Key
      # Send request.
      headers = {
          'Content-Type': 'application/json',
          'Authorization': f'Bearer {api_key}'
      }
      data = {
          "model": "deepseek-v4-flash",
          "messages" : [{
                  "role" : "user",
                  "content" : "下面是一个红楼梦中的场景，请按照指定的角色来进行对话，每轮对话只用回复当前角色的内容，不要再回复新的内容。刘姥姥别了村舍，进城而来，不一时行至一所府邸前。但见朱门高墙，雕梁画栋，门前石狮威武，门第森严。"
              }, {
                  "role" : "assistant",
                  "content" : "刘姥姥说:",
                  "prefix" : True
              }
          ],
          "temperature": 0.6,
          "stream": False
      }
      response = requests.post(url, headers=headers, data=json.dumps(data), verify=False)
      with open('response.txt', 'w', encoding='utf-8') as f:
          f.write(f"Status Code: {response.status_code}\n")
          f.write("Response Content:\n")
          f.write(response.text)
      # Print result.
      print(response.status_code)
      print(response.text)
  ```
  输出内容：
  ```
  阿弥陀佛，这可比我们乡下气派多了。我得先打听打听，这是不是贾府啊？（对路过行人）请问这位大哥，这可是荣国府？
  ```
- [OpenAI兼容接口]
  ```
  #Python
  import requests
  import json
  if __name__ == '__main__':
      url = "https://api.modelarts-maas.com/openai/v1/chat/completions"  # API地址
      api_key = "MAAS_API_KEY"  # 把MAAS_API_KEY替换成已获取的API Key
      # Send request.
      headers = {
          'Content-Type': 'application/json',
          'Authorization': f'Bearer {api_key}'
      }
      data = {
          "model": "deepseek-v4-flash",
          "continue_final_message":True,
          "add_generation_prompt":False,
          "messages" : [{
                  "role" : "user",
                  "content" : "下面是一个红楼梦中的场景，请按照指定的角色来进行对话，每轮对话只用回复当前角色的内容，不要再回复新的内容。刘姥姥别了村舍，进城而来，不一时行至一所府邸前。但见朱门高墙，雕梁画栋，门前石狮威武，门第森严。"
              }, {
                  "role" : "assistant",
                  "content" : "刘姥姥说:",
                  "prefix" : True
              }
          ],
          "temperature": 0.6,
          "stream": False
      }
      response = requests.post(url, headers=headers, data=json.dumps(data), verify=False)
      with open('response.txt', 'w', encoding='utf-8') as f:
          f.write(f"Status Code: {response.status_code}\n")
          f.write("Response Content:\n")
          f.write(response.text)
      # Print result.
      print(response.status_code)
      print(response.text)
  ```
  输出内容：
  ```
  阿弥陀佛，这可比我们乡下气派多了。我得先打听打听，这是不是贾府啊？（对路过行人）请问这位大哥，这可是荣国府？
  ```
#### 场景二：输出超过模型输出上限的内容
由于大模型存在单次输出长度限制，可能导致长内容无法完整输出。前缀续写可根据前轮请求续写内容，多次拼接输出内容，组成超长输出内容。以下为Python示例代码，可通过model参数替换模型，model参数详情请参见[文本生成](https://support.huaweicloud.com/model-list-maas/model_list_0001.html#section1)。
```
#Python
import requests
import json
import os
def continuous_generate():
    url = "https://api.modelarts-maas.com/v2/chat/completions"
    api_key = "MAAS_API_KEY"
    # 初始消息
    messages = [
        {"role": "user", "content":"请以童话故事为主题续写下面的故事：一片翠绿的森林里，住着一只名叫小白的兔子。"},
        {"role": "assistant", "content": "", "prefix": True}
    ]
    headers = {
        'Content-Type': 'application/json',
        'Authorization': f'Bearer {api_key}'
    }
    full_response_content = messages[-1]["content"]  # 记录已完成的内容
    loop_count = 0
    max_loops = 30  # 最大循环次数防死循环
    while True:
        data = {
            "model": "deepseek-v4-flash",
            "messages": messages,
            "temperature": 0.6,
            "stream": False
        }
        response = requests.post(url, headers=headers, data=json.dumps(data), verify=False)
        if response.status_code != 200:
            print("Error:", response.text)
            break
        result = response.json()
        choice = result['choices'][0]
        finish_reason = choice.get('finish_reason')
        content = choice['message']['content']
        # 拼接新内容到历史回复中
        full_response_content += content
        # 更新 assistant 的 content 为当前完整的累计内容
        messages[-1]["content"] = full_response_content
        loop_count += 1
   # 如果达到最大轮数或 finish_reason 不是 length 则停止
        if finish_reason != "length" or loop_count >= max_loops:
            if loop_count >= max_loops:
                print(f" Reached max loop limit {max_loops}, stopped.")
            break
    # 最终输出全量内容
    print(" Final Complete Content:")
    print(full_response_content)
    # 可选写入文件
    with open("final_output.txt", "w", encoding="utf-8") as f:
        f.write(full_response_content)
if __name__ == "__main__":
    continuous_generate()
```
模型输出示例：
```
Final Complete Content:
好的，我们接着这个开头，来编织一个通话故事：
---
一片翠绿的森林里，住着一只名叫小白的兔子。小白和别的兔子有点不一样，它那双红宝石般的眼睛，总是痴迷地望着森林深处那棵最高最老的橡树。因为兔奶奶说过，在那棵橡树的树洞里，藏着一部古老的**“月光电话”**。据说，在每年月亮最圆的那个晚上，电话会短暂地接通，能打给任何一个你想念的人，哪怕他在很远很远的地方，甚至……在另一个世界。
小白想念爷爷。爷爷在去年落叶最金黄的时候，去了一个叫“星星草原”的远方，再也没有回来。
于是，小白等啊等，从春天等到夏天。终于，中秋的满月像一面银盘，升上了夜空。小白鼓起勇气，穿过挂着露珠的草丛，绕过打着鼾的刺猬，来到了老橡树下。树洞幽深，里面果然躺着一部用藤蔓缠绕、贝壳做听筒的奇妙电话。它正散发着柔和的、珍珠般的光泽。
小白的心怦怦跳，它踮起脚，小心翼翼地拿起听筒。里面传来“沙沙”的声响，像是风吹过星际的声音。它深吸一口气，对着贝壳话筒轻轻地说：“喂……请问，能帮我接通星星草原吗？我想找我的爷爷。”
电话那头静默了片刻，然后，“沙沙”声变成了潺潺流水般悦耳的旋律。一个温暖、熟悉，仿佛带着阳光和干草香味的声音响了起来：“嘿，我的小小白，是你吗？你的长耳朵是不是又长大了一点？”
是爷爷！小白的眼泪一下子涌了出来，它使劲点头，好像爷爷能看到一样：“爷爷！是我！您的耳朵还是那么灵！我……我很好，我跑得比以前更快了，找到了新的胡萝卜田，但……但我很想您。星星草原……是什么样子的？”
爷爷的声音充满了笑意：“这里啊，柔软极了，像云朵做的地毯，长满了会发光的浆果，永远都是舒服的黄昏天色。我交了很多新朋友，有爱讲笑话的流星獾，还有沉默但善良的巨角星鹿。我每天都在最高的草坡上，能看到咱们的森林呢。”
“真的吗？那您能看到我吗？”小白急切地问。
“当然，”爷爷的声音温柔得像月光，“我看到你勇敢地跳过小溪，看到你帮迷路的小鸟找家，还看到你……有时坐在洞口，看着天空发呆。我的小小白长大啦，变得又善良又勇敢。”
小白感到心里暖暖的，又酸酸的。“爷爷，我有时候会害怕，怕黑，怕打雷……”
“记住，孩子，”爷爷的声音坚定而充满力量，“恐惧就像森林里的影子，看起来很大，但你勇敢地走过去，它就跑到你身后去了。你的勇气在心里，就像种子在泥土里，它一直在生长。听听你的心跳，那是最响亮的鼓声，它会带领你向前。”
他们聊了好久，聊森林里的新闻，聊小白新学的跳跃技巧，聊爷爷在星星草原的趣事。月亮渐渐西斜，电话里的“沙沙”声又开始变大了。
“小小白，”爷爷的声音变得轻微，但依旧清晰，“月光电话的电量，是月光的礼物，它快要用完了。记住爷爷的话：爱是永远不会挂断的通话。当你闻到风中的花香，那是我在问候你；当你看到闪烁的星星，那是我在对你眨眼睛。我从未离开，只是换了一种方式陪伴你。”
“爷爷，我……”小白哽咽着。
“要快乐地奔跑，尽情地长大。替我多吃几根清甜的胡萝卜。再见，我的宝贝。” 爷爷的声音带着笑意，渐渐融入了那片“沙沙”的星际风声之中。
电话的光芒暗了下去，恢复了平静。小白轻轻放下听筒，脸上还挂着泪珠，但心里却像被月光洗过一样，明亮而踏实。它走出树洞，仰头望着满天繁星。其中有一颗，格外温暖，格外明亮，正对着它温柔地闪烁。
小白知道，那一定是爷爷。从那天起，小白变得更开朗，更勇敢。它依然热爱奔跑，但也会时常停下来，闻闻花香，看看星星，然后对着夜空，露出一个心照不宣的微笑。
因为它知道，无论相隔多远，爱与思念的信号，永远满格。那部古老的月光电话，其实一直连通在它的心里。
---
这就是小白兔和月光电话的故事，一个关于思念、勇气和永恒联结的童话。希望你喜欢这个温暖的结局。
进程已结束，退出代码为 0
```
