Skip to content

Completion 单次会话输出

Completion 主要用于 AI 单次内容生成的实现,帮助业务快速搭建自己的 AI 内容生成功能。支持 React、Vue2、Vue3 和微信小程序等多个技术栈。

设计理念

Completion SDK 基于 Headless UI 概念设计,专注于提供数据状态管理和业务逻辑处理,不包含任何预置的 UI 组件

优点:

  • 🎨 高度可定制化:完全自由地设计和实现 UI 界面
  • 🔧 灵活性强:适配各种设计系统和 UI 框架
  • 📦 轻量级:不包含 UI 代码,包体积更小
  • 🔄 技术栈无关:可与任何 UI 库或组件库结合使用
  • 单次生成:专注于单次 AI 内容生成,无历史消息管理

注意事项:

  • ⚠️ 需要自行实现 UI:开发者需要根据业务需求自行设计和实现生成界面
  • 🛠️ 需要处理样式:输入框、按钮、内容展示等 UI 元素需要自行开发
  • 📱 适配工作:不同平台的 UI 适配需要开发者自行处理

与 Chat 的区别:

  • Chat:支持多轮对话,维护消息历史记录
  • Completion:单次内容生成,无消息历史,专注于文本生成任务

架构图

下图展示了 Completion SDK 的三层架构关系:

架构说明

  • UI 组件层:各种 UI 组件库和自定义组件,负责内容生成界面展示
  • Completion SDK 层:🎯 核心抽象层,提供 Headless UI 的状态管理和业务逻辑,支持多端适配
  • AI 模型层:各种大语言模型,提供 AI 内容生成能力

Completion SDK 的核心价值

  • 📦 解耦 UI 与逻辑:UI 层可以自由选择,SDK 专注于状态管理
  • 🔄 统一多端接口:一套 API 适配多个技术栈和 AI 模型
  • 🛠️ 简化开发复杂度:封装网络通信、状态管理等底层细节
  • 专注内容生成:优化单次生成场景,提供精确的状态控制

使用方法

jsx
import { useCompletion } from '@tencent/ssv-ai-sdk-react';

function CompletionComponent() {
  const { content, status, error, extraInfo, generate, stop, setOptions } =
    useCompletion({
      api: {
        completionEndpoint: {
          url: 'https://api.example.com/completion',
          requestInterceptor: (options) => ({
            ...options,
            headers: {
              ...options.headers,
              Authorization: 'Bearer your-token',
            },
          }),
        },
      },
      mode: 'stream',
      streamFormat: 'incremental',
    });

  const handleGenerate = async () => {
    await generate({
      prompt: '请写一篇关于人工智能的文章',
      max_tokens: 1000,
    });
  };

  return (
    <div>
      <button onClick={handleGenerate} disabled={status === 'loading'}>
        {status === 'loading' ? '生成中...' : '开始生成'}
      </button>
      {status === 'loading' && <button onClick={stop}>停止生成</button>}
      <div className="content-area">{content && <pre>{content}</pre>}</div>
      {error && <div className="error">{error.message}</div>}
    </div>
  );
}
vue
<template>
  <div>
    <button @click="handleGenerate" :disabled="status === 'loading'">
      {{ status === 'loading' ? '生成中...' : '开始生成' }}
    </button>
    <button v-if="status === 'loading'" @click="stop">停止生成</button>
    <div class="content-area">
      <pre v-if="content">{{ content }}</pre>
    </div>
    <div v-if="error" class="error">
      {{ error.message }}
    </div>
  </div>
</template>

<script setup>
import { useCompletion } from '@tencent/ssv-ai-sdk-vue3';

const { content, status, error, extraInfo, generate, stop, setOptions } =
  useCompletion({
    api: {
      completionEndpoint: {
        url: 'https://api.example.com/completion',
        requestInterceptor: (options) => ({
          ...options,
          headers: {
            ...options.headers,
            Authorization: 'Bearer your-token',
          },
        }),
      },
    },
    mode: 'stream',
    streamFormat: 'incremental',
  });

const handleGenerate = async () => {
  await generate({
    prompt: '请写一篇关于人工智能的文章',
    max_tokens: 1000,
  });
};
</script>
vue
<template>
  <div>
    <button @click="handleGenerate" :disabled="completion.status === 'loading'">
      {{ completion.status === 'loading' ? '生成中...' : '开始生成' }}
    </button>
    <button v-if="completion.status === 'loading'" @click="handleStop">
      停止生成
    </button>
    <div class="content-area">
      <pre v-if="completion.content">{{ completion.content }}</pre>
    </div>
    <div v-if="completion.error" class="error">
      {{ completion.error.message }}
    </div>
  </div>
</template>

<script>
import { CompletionMixin } from '@tencent/ssv-ai-sdk-vue2';

export default {
  mixins: [
    CompletionMixin({
      api: {
        completionEndpoint: {
          url: 'https://api.example.com/completion',
          requestInterceptor: (options) => ({
            ...options,
            headers: {
              ...options.headers,
              Authorization: 'Bearer your-token',
            },
          }),
        },
      },
      mode: 'stream',
      streamFormat: 'incremental',
    }),
  ],

  methods: {
    async handleGenerate() {
      await this.ai.generate({
        prompt: '请写一篇关于人工智能的文章',
        max_tokens: 1000,
      });
    },

    handleStop() {
      this.ai.stop();
    },
  },
};
</script>
js
// pages/completion/completion.js
import { CompletionBehavior } from '@tencent/ssv-ai-sdk-miniprogram';

Component({
  behaviors: [
    CompletionBehavior({
      api: {
        completionEndpoint: {
          url: 'https://api.example.com/completion',
          requestInterceptor: (options) => ({
            ...options,
            headers: {
              ...options.headers,
              Authorization: 'Bearer your-token',
            },
          }),
        },
      },
      mode: 'stream',
      streamFormat: 'incremental',
    }),
  ],

  data: {
    prompt: '',
  },

  methods: {
    handleInput(e) {
      this.setData({ prompt: e.detail.value });
    },

    async handleGenerate() {
      await this.ai.generate({
        prompt: this.data.prompt,
        max_tokens: 1000,
      });
    },

    handleStop() {
      this.ai.stop();
    },
  },
});

配置 Config

api.completionEndpoint

定义 AI 内容生成接口,配置 urlrequestInterceptorresponseInterceptor

js
{
  api: {
    completionEndpoint: {
      url: 'https://api.example.com/completion',
      requestInterceptor: (options) => {
        // 添加认证信息
        return {
          ...options,
          headers: {
            ...options.headers,
            'Authorization': 'Bearer your-token',
            'X-API-Version': 'v1'
          }
        };
      },
      responseInterceptor: (data) => {
        // 处理响应数据格式转换
        return {
          content: data.text || data.content,
          extraInfo: {
            usage: data.usage,
            model: data.model
          }
        };
      }
    }
  }
}

api.completionEndpoint.requestInterceptor

请求拦截器,用于对发送给 AI 接口的请求进行拦截和修改。主要用于添加自定义请求头、身份验证信息或其他请求参数。

typescript
interface RequestInterceptor {
  (options: RequestOptions): RequestOptions;
}

interface RequestOptions {
  headers?: Record<string, any>;
  data?: any;
  [key: string]: any;
}

常见使用场景:

  • 添加身份验证令牌
  • 设置自定义请求头
  • 添加 API 版本信息
  • 修改请求参数格式

api.completionEndpoint.responseInterceptor

响应拦截器,用于处理 AI 接口返回的数据格式转换。

typescript
interface ResponseInterceptor {
  (data: any): {
    content?: string;
    extraInfo?: Record<string, any>;
    error?: any;
  };
}

mode 模式

接口模式,可选 httpstream

  • stream:流式数据,实时获取生成内容(推荐)
  • http:一次性返回完整内容
js
{
  mode: 'stream'; // 或 'http'
}

streamFormat 流式格式

流式格式输出,可选 incrementalchunked。影响内容 content 的输出方式。

  • incremental:增量返回,每次返回的内容会累加到之前的内容
  • chunked:分块返回,每次返回完整的当前内容
js
{
  streamFormat: 'incremental'; // 或 'chunked'
}

json JSON 模式

是否启用 JSON 模式输出,当设置为 true 时,会尝试解析返回的内容为 JSON 格式。

js
{
  json: true; // 启用 JSON 模式
}

数据 State

content 生成内容

AI 生成的文本内容,实时更新:

jsx
function Component() {
  const { content } = useCompletion({
    // 配置...
  });

  return <div>{content}</div>;
}
vue
<template>
  <div>{{ content }}</div>
</template>

<script setup>
const { content } = useCompletion({
  // 配置...
});
</script>
vue
<template>
  <div>{{ completion.content }}</div>
</template>

<script>
export default {
  mixins: [
    CompletionMixin({
      // 配置...
    }),
  ],
};
</script>
html
<!-- WXML 模板 -->
<view class="content">{{completion.content}}</view>

jsonContent JSON 内容

当启用 JSON 模式时,解析后的 JSON 对象:

jsx
const { jsonContent } = useCompletion({
  json: true,
});

// jsonContent 将包含解析后的 JSON 对象
console.log(jsonContent);

extraInfo 额外信息

存储 AI 接口返回的额外信息,如使用统计、模型信息等:

typescript
interface ExtraInfo {
  usage?: {
    prompt_tokens: number;
    completion_tokens: number;
    total_tokens: number;
  };
  model?: string;
  [key: string]: any;
}
jsx
function Component() {
  const { extraInfo } = useCompletion({
    // 配置...
  });

  return (
    <div>
      <p>使用的模型: {extraInfo.model}</p>
      <p>Token 使用量: {extraInfo.usage?.total_tokens}</p>
    </div>
  );
}
vue
<template>
  <div>
    <p>使用的模型: {{ extraInfo.model }}</p>
    <p>Token 使用量: {{ extraInfo.usage?.total_tokens }}</p>
  </div>
</template>
vue
<template>
  <div>
    <p>使用的模型: {{ completion.extraInfo.model }}</p>
    <p>
      Token 使用量:
      {{
        completion.extraInfo.usage && completion.extraInfo.usage.total_tokens
      }}
    </p>
  </div>
</template>
html
<!-- WXML 模板 -->
<view>
  <text>使用的模型: {{completion.extraInfo.model}}</text>
  <text>Token 使用量: {{completion.extraInfo.usage.total_tokens}}</text>
</view>

status 生成状态

表示当前生成任务的状态:

  • idle:空闲状态,未开始生成
  • loading:生成中
  • success:生成成功完成
  • failed:生成失败
  • stopped:生成被停止
jsx
function Component() {
  const { status, generate, stop } = useCompletion({});

  return (
    <div>
      <button
        onClick={() => generate({ prompt: 'Hello' })}
        disabled={status === 'loading'}
      >
        {status === 'loading' ? '生成中...' : '开始生成'}
      </button>
      {status === 'loading' && <button onClick={stop}>停止</button>}
    </div>
  );
}
vue
<template>
  <div>
    <button
      @click="generate({ prompt: 'Hello' })"
      :disabled="status === 'loading'"
    >
      {{ status === 'loading' ? '生成中...' : '开始生成' }}
    </button>
    <button v-if="status === 'loading'" @click="stop">停止</button>
  </div>
</template>
vue
<template>
  <div>
    <button @click="handleGenerate" :disabled="completion.status === 'loading'">
      {{ completion.status === 'loading' ? '生成中...' : '开始生成' }}
    </button>
    <button v-if="completion.status === 'loading'" @click="handleStop">
      停止
    </button>
  </div>
</template>

<script>
export default {
  methods: {
    async handleGenerate() {
      await this.ai.generate({ prompt: 'Hello' });
    },
    handleStop() {
      this.ai.stop();
    },
  },
};
</script>
html
<!-- WXML 模板 -->
<view>
  <button
    bindtap="handleGenerate"
    disabled="{{completion.status === 'loading'}}"
  >
    {{completion.status === 'loading' ? '生成中...' : '开始生成'}}
  </button>
  <button wx:if="{{completion.status === 'loading'}}" bindtap="handleStop">
    停止
  </button>
</view>

<!-- JavaScript -->
<script>
  Page({
    async handleGenerate() {
      await this.ai.generate({ prompt: 'Hello' });
    },

    handleStop() {
      this.ai.stop();
    },
  });
</script>

error 错误信息

当生成过程中发生错误时,包含错误详情:

typescript
interface AIError {
  message: string;
  code?: string;
  cause?: any;
}
jsx
function Component() {
  const { error } = useCompletion({});

  if (error) {
    return <div className="error">错误: {error.message}</div>;
  }

  return null;
}
vue
<template>
  <div v-if="error" class="error">错误: {{ error.message }}</div>
</template>
vue
<template>
  <div v-if="completion.error" class="error">
    错误: {{ completion.error.message }}
  </div>
</template>
html
<!-- WXML 模板 -->
<view wx:if="{{completion.error}}" class="error">
  错误: {{completion.error.message}}
</view>

方法 Methods

generate() 开始生成

启动 AI 内容生成:

typescript
interface CompletionParams {
  prompt?: string;
  max_tokens?: number;
  temperature?: number;
  [key: string]: any;
}

async function generate(params: CompletionParams): Promise<void>;

使用示例:

jsx
const { generate } = useCompletion({});

await generate({
  prompt: '写一首关于春天的诗',
  max_tokens: 500,
  temperature: 0.7,
});
vue
const { generate } = useCompletion({}); await generate({ prompt:
'写一首关于春天的诗', max_tokens: 500, temperature: 0.7 });
vue
// 在组件方法中 async handleGenerate() { await this.ai.generate({ prompt:
'写一首关于春天的诗', max_tokens: 500, temperature: 0.7 }); }
js
// 在页面方法中
async handleGenerate() {
  await this.ai.generate({
    prompt: '写一首关于春天的诗',
    max_tokens: 500,
    temperature: 0.7
  });
}

stop() 停止生成

停止当前正在进行的生成任务:

jsx
const { stop } = useCompletion({});

const handleStop = () => {
  stop();
};
vue
const { stop } = useCompletion({}); const handleStop = () => { stop(); };
vue
handleStop() { this.ai.stop(); }
js
handleStop() {
  this.ai.stop();
}

setOptions() 更新配置

动态更新 SDK 配置:

typescript
function setOptions(options: Partial<CompletionOptions>): void;

使用示例:

jsx
const { setOptions } = useCompletion({});

// 更新 API 端点
setOptions({
  api: {
    completionEndpoint: {
      url: 'https://new-api.example.com/completion',
    },
  },
});

// 更新流式格式
setOptions({
  streamFormat: 'chunked',
});
vue
const { setOptions } = useCompletion({}); setOptions({ mode: 'http', json: true
});
vue
this.ai.setOptions({ streamFormat: 'incremental' });
js
this.ai.setOptions({
  mode: 'stream',
});

事件 Events

on() 监听事件

监听 SDK 内部事件:

typescript
function on(event: string, callback: (...args: any[]) => void): void;

可用事件

'content' 内容更新事件

当生成内容更新时触发:

js
ai.on('content', (content) => {
  console.log('内容更新:', content);
});

'message' 原始消息事件

接收 AI 接口返回的原始数据:

js
ai.on('message', (rawData) => {
  console.log('原始数据:', rawData);
});

'state_change' 状态变化事件

当 SDK 状态发生变化时触发:

js
ai.on('state_change', (state) => {
  console.log('状态变化:', state);
});

使用示例:

jsx
const { ai } = useCompletion({});

useEffect(() => {
  const handleContent = (content) => {
    console.log('内容更新:', content);
  };

  ai.on('content', handleContent);

  return () => {
    ai.off('content', handleContent);
  };
}, [ai]);
vue
const { ai } = useCompletion({}); onMounted(() => { const handleContent =
(content) => { console.log('内容更新:', content); }; ai.on('content',
handleContent); onUnmounted(() => { ai.off('content', handleContent); }); });
vue
mounted() { this.ai.on('content', this.handleContent); }, beforeDestroy() {
this.ai.off('content', this.handleContent); }, methods: { handleContent(content)
{ console.log('内容更新:', content); } }
js
onLoad() {
  this.ai.on('content', this.handleContent);
},

onUnload() {
  this.ai.off('content', this.handleContent);
},

handleContent(content) {
  console.log('内容更新:', content);
}

最佳实践

1. 错误处理

jsx
const { generate, error, status } = useCompletion({});

const handleGenerate = async () => {
  try {
    await generate({ prompt: 'Hello' });
  } catch (err) {
    console.error('生成失败:', err);
    // 处理错误
  }
};

// 在 UI 中显示错误
if (error) {
  return <div className="error">生成失败: {error.message}</div>;
}

2. 流式内容展示

jsx
const { content, status } = useCompletion({
  mode: 'stream',
  streamFormat: 'incremental',
});

return (
  <div>
    <pre className="content-area">{content}</pre>
    {status === 'loading' && (
      <div className="loading-indicator">正在生成...</div>
    )}
  </div>
);

3. JSON 模式使用

jsx
const { jsonContent, generate } = useCompletion({
  json: true,
});

const handleGenerate = async () => {
  await generate({
    prompt: '请返回一个包含姓名和年龄的JSON对象',
  });
};

// jsonContent 将包含解析后的对象
console.log(jsonContent); // { name: "张三", age: 25 }

4. 自定义请求处理

js
const completion = useCompletion({
  api: {
    completionEndpoint: {
      url: '/api/completion',
      requestInterceptor: (options) => ({
        ...options,
        headers: {
          ...options.headers,
          Authorization: `Bearer ${getToken()}`,
          'X-User-ID': getCurrentUserId(),
        },
      }),
      responseInterceptor: (data) => ({
        content: data.result?.text || '',
        extraInfo: {
          usage: data.usage,
          model: data.model_name,
        },
      }),
    },
  },
});

Released under the MIT License.