Commit b40dc588 by renyizhao

使用指南

parent cf1b2f23
/**
* 新 NewAPI 模型使用方式 - Profile 配置
*
* 移植自 newapi/web/src/features/pricing/lib/api-example-profiles.ts
* 适配 Vue3 + JavaScript
*
* 负责:
* 1) profile 名称 → 中文标签映射
* 2) profile → 支持的场景列表(basic / image-reference / video-reference)
* 3) profile + endpoint + scenario → 专属请求体
* 4) profile + endpoint + scenario → 专属参数补充
*/
/** 场景类型 */
export const SCENARIO_LABELS = {
basic: '基础示例',
'image-reference': '图片参考',
'video-reference': '视频参考',
}
/** Profile 标签映射(与新 NewAPI 保持一致) */
export const PROFILE_LABELS = {
standard: '基础示例',
'ctyun-h3': 'MiniMax H3',
seedance: 'Seedance',
seedance2: 'Seedance 2.0',
'ctyun-wan': 'Wan / HappyHorse',
'ctyun-wan-image': 'Wan / HappyHorse I2V',
'ctyun-wan3': 'Wan 3.0',
'ctyun-wan-reference': 'Wan 2.7 R2V',
'ctyun-happyhorse-reference': 'HappyHorse R2V',
'ctyun-seedream': 'Seedream',
'ctyun-seedream-pro': 'Seedream 5.0 pro',
'ctyun-message-image': 'Qwen / Wan Image',
'ctyun-message-image-edit': 'Qwen / Wan Image Edit',
'ctyun-qwen-rerank': 'Qwen Rerank',
'ctyun-gte-rerank': 'GTE Rerank',
'ctyun-vl-embedding': 'Qwen VL Embedding',
}
/**
* 合并同 endpoint 的多个 api_examples 条目(按 profile 去重,providers/groups 取并集)
*/
export function mergeAPIExamples(examples, endpoint) {
const merged = new Map()
for (const example of examples || []) {
if (example.endpoint !== endpoint) continue
const previous = merged.get(example.profile)
merged.set(example.profile, {
...example,
providers: [
...new Set([...(previous?.providers ?? []), ...(example.providers ?? [])]),
].sort(),
groups: [
...new Set([...(previous?.groups ?? []), ...(example.groups ?? [])]),
].sort(),
})
}
return [...merged.values()]
}
/**
* 返回某个 profile 支持的场景列表
*/
export function exampleScenarios(profile) {
if (['ctyun-wan-reference'].includes(profile)) {
return ['image-reference', 'video-reference']
}
if (
[
'ctyun-happyhorse-reference',
'ctyun-wan-image',
'ctyun-message-image-edit',
].includes(profile)
) {
return ['image-reference']
}
if (['ctyun-h3', 'seedance2', 'ctyun-wan3'].includes(profile)) {
return ['basic', 'image-reference', 'video-reference']
}
if (
[
'seedance',
'ctyun-seedream',
'ctyun-seedream-pro',
'ctyun-message-image',
].includes(profile)
) {
return ['basic', 'image-reference']
}
return ['basic']
}
/**
* 根据 (model, endpoint, profile, scenario) 生成专属请求体
* 如果不需要专属请求体(例如 standard),返回 undefined,由默认 builder 处理
*
* @returns {object|undefined}
*/
export function profileRequest(model, endpoint, profile, scenario) {
if (!PROFILE_LABELS[profile] || profile === 'standard') return undefined
if (endpoint === 'openai-video') {
const wan = profile.includes('wan') || profile.includes('happyhorse')
const body = {
model,
prompt: 'A calm lake at sunset.',
seconds: '5',
resolution: profile === 'ctyun-h3' ? '768P' : '1080P',
}
const seedance = profile.startsWith('seedance')
if (seedance) {
delete body.resolution
body.metadata = { resolution: '1080p' }
}
if (profile === 'ctyun-h3') body.ratio = '16:9'
if (scenario !== 'basic') {
const video = scenario === 'video-reference'
const url = video
? 'https://example.com/reference.mp4'
: 'https://example.com/reference.jpg'
if (wan) {
if (profile === 'ctyun-wan-image') {
body.image = url
} else {
body.metadata = {
input: {
media: [
{ type: video ? 'reference_video' : 'reference_image', url },
],
},
}
}
} else {
const type = video ? 'video_url' : 'image_url'
body.metadata = {
...(seedance ? { resolution: '1080p' } : {}),
content: [
{
type,
[type]: { url },
role: video ? 'reference_video' : 'first_frame',
},
],
}
}
}
return body
}
if (endpoint === 'image-generation') {
return {
model,
prompt: 'A calm lake at sunset.',
size: profile.includes('seedream') ? '2K' : '1024x1024',
n: 1,
stream: false,
...(scenario === 'image-reference'
? { image: 'https://example.com/reference.jpg' }
: {}),
}
}
if (endpoint === 'jina-rerank') {
return {
model,
query: 'What is the capital of China?',
documents: [
'Beijing is the capital of China.',
'Shanghai is a major city.',
],
top_n: 1,
...(profile === 'ctyun-qwen-rerank'
? { instruct: 'Rank documents by relevance to the query.' }
: { return_documents: true }),
}
}
if (endpoint === 'embeddings' && profile === 'ctyun-vl-embedding') {
return {
model,
input: {
contents: [
{ text: 'A calm lake.' },
{ image: 'https://example.com/reference.jpg' },
],
},
encoding_format: 'float',
dimensions: 1024,
}
}
return undefined
}
/**
* 在基础参数表上叠加 profile 专属参数
*
* @param {Array} base - 基础参数列表(来自 buildSupportedParameters)
* @param {string} endpoint
* @param {string} profile
* @param {string} scenario
* @returns {Array}
*/
export function profileParameters(base, endpoint, profile, scenario) {
if (!PROFILE_LABELS[profile] || profile === 'standard') return base
let params = base.map((p) => ({ ...p }))
if (endpoint === 'openai-video') {
params = params.filter((p) => p.name !== 'size')
params.push({
name: profile.startsWith('seedance')
? 'metadata.resolution'
: 'resolution',
type: 'enum',
enumValues:
profile === 'ctyun-h3'
? ['480P', '768P', '2K']
: ['480P', '720P', '1080P'],
descriptionKey: '输出分辨率',
})
if (profile === 'ctyun-h3') {
params.push({
name: 'ratio',
type: 'string',
descriptionKey: '输出宽高比。H3 帧输入自适应;纯文本输入需显式指定 ratio。',
})
}
if (scenario !== 'basic') {
const wan = profile.includes('wan') || profile.includes('happyhorse')
if (profile === 'ctyun-wan-image') {
params.push({
name: 'image',
type: 'string',
required: true,
descriptionKey: '输入图片 URL 或图片 URL 数组,用于图片编辑。',
})
} else {
params.push({
name: wan ? 'metadata.input.media' : 'metadata.content',
type: 'array',
required: true,
descriptionKey: wan
? '高级视频输入:input.media 包含类型化媒体 URL;不要混用帧输入与参考输入。'
: '高级视频输入:content 包含 text、image_url、video_url 或 audio_url 项,可指定 role。',
})
}
}
}
if (endpoint === 'image-generation') {
if (scenario === 'image-reference') {
params.push({
name: 'image',
type: 'string',
required: true,
descriptionKey: '输入图片 URL 或图片 URL 数组,用于图片编辑。',
})
}
params.push({
name: 'stream',
type: 'boolean',
defaultValue: false,
descriptionKey: '此适配器中 Qwen/万相图像和 Seedream 5.0 pro 必须使用 stream=false。',
})
const size = params.find((p) => p.name === 'size')
if (size) {
size.descriptionKey = profile.includes('seedream')
? '使用模型支持的图像尺寸,例如 Seedream 推荐 2K。'
: '使用 WIDTHxHEIGHT(每边 512~2048);Wan 同时支持 1K、2K、4K。原生参数 size 使用 WIDTH*HEIGHT。'
}
if (profile.includes('message-image')) {
params.push({
name: 'parameters',
type: 'object',
descriptionKey: '原生图像参数覆盖顶层的 size 和 watermark;需要时可在此填 size、n、seed。',
})
}
}
if (endpoint === 'jina-rerank') {
params.push(
profile === 'ctyun-qwen-rerank'
? {
name: 'instruct',
type: 'string',
descriptionKey: '可选的重排序指令',
}
: {
name: 'return_documents',
type: 'boolean',
descriptionKey: '是否在重排结果中包含文档原文',
}
)
}
if (profile === 'ctyun-vl-embedding') {
params = params.map((p) =>
p.name === 'input'
? {
...p,
type: 'object',
descriptionKey:
'使用 input.contents;每项恰好包含一个非空的 text、image 或 video 字符串。',
}
: p
)
const encoding = params.find((p) => p.name === 'encoding_format')
if (encoding) encoding.enumValues = ['float']
}
return params
}
\ No newline at end of file
/**
* 新 NewAPI 模型使用方式 - 统一导出
*
* 在 puhui 客户端复用 NewAPI 前端代码模板与参数定义
* 来源:newapi/web/src/features/pricing/lib/
*/
// 代码模板
export { buildSample } from './code-samples.js'
// Profile 配置
export {
SCENARIO_LABELS,
PROFILE_LABELS,
mergeAPIExamples,
exampleScenarios,
profileRequest,
profileParameters,
} from './example-profiles.js'
// 参数定义
export {
COMMON_CHAT_PARAMS,
REASONING_PARAMS,
EMBEDDING_PARAMS,
IMAGE_PARAMS,
VIDEO_PARAMS,
buildSchemaParams,
buildEndpointParameters,
} from './api-parameters.js'
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or sign in to comment