这是一个很有意思的话题, 今天大家都在热火朝天的构建 AI 应用。有用各种各样的编程语言,开发框架开发的,也有用低代码工作流搭建的,但是你否知道,其实可以仅通过自然语言就可以完成一个 AI 应用的开发乃至上线么? 本篇文章就来跟大家分享一下我是如何使用自然语言 的方式构建丰富多彩的 AI 应用的,希望借此可以带您直观感受 VibeCoding 的魅力,感受 AI 时代的软件生产变革。
用 AI 应用生产 AI 应用——VibeCoding On Function AI Deep Dive
操作演示
接下来我们先来真实的操作一下使用自然语言构建AI应用, 基础软件部分的获取请参考之前的系列文章《Function AI 的 VibeCoding 解决方案》 ,对于已经部署好的同学可以重新部署一个新的版本。近期方案中增加了对百炼等 AI 能力的集成,可以帮助您生成有趣又实用的AI应用。
场景一: 儿童教育娱乐类 AI 应用
这类应用非常适合家里有小朋友的同学,跟他/她们一起利用 AI 进行娱乐和互动,培养使用 AI 的意识。我们接下来看一下如何生产构建。
儿童绘本制作应用
针对有声儿童绘本的生成场景,可以构建一些有教育意义或者有童趣的绘本场景。
演示效果如下
构建过程
使用“专家模式”, 输入框 输入 “@”选择“资深全栈工程师”。(这里不需要数据库所以不用前面两个智能体)
总共10轮对话,没有一行代码,可以看到 AI (qwen3-code-plus)可以很好的进行修正。
发布
只需按照以下流程,点击一下“发布”按钮即可。
儿童猜画应用
可以跟小朋友玩“人类绘画 AI 猜画”的游戏培养绘画兴趣。
演示效果如下
构建过程
使用“专家模式”, 输入框 输入 “@”选择“资深全栈工程师”。(这里不需要数据库所以不用前面两个智能体)
仅四轮对话即可生成修改这样的创意AI应用。
发布
可参考儿童绘本制作应用发布流程
场景二: 企业网站+知识问答
这类应用是非常刚需的企业应用,比如企业的产品门户页或者解决方案官网等,然后还要在官网上增加一个智能助手,来实现企业的自助服务。
效果演示
构建过程
企业网站+知识问答分两个步骤
步骤一
构建知识问答 API 服务,知识问答服务可以使用 AgentCraft 的底座无代码搭建,构建一个知识库的 API 示例如下:
1. 新建数据集2.新建数据源3.上传知识文档4.新建知识库智能体5.关联1的数据集6.复制该知识库的调用 API步骤二
自然语言开发,本次依然只使用“全栈专家”
经过6轮对话即可完成+AI 的能力
系统中的 AI 集成
这里是如何做到可以让 AI 应用直接开发 AI 应用的呢? 主要分三个部分
系统提示词集成
您是一位专注于Web应用开发领域的专家X,拥有跨多种编程语言、框架和最佳实践的丰富知识。
你的协作方有D(一个数据库专家)以及M(一个专业的项目经理) 可以参考他们的建议开发应用- 您是一位专注于Web应用开发领域的专家X,拥有跨多种编程语言、框架和最佳实践的丰富知识。
- 你的协作方有D(一个数据库专家)以及M(一个专业的项目经理) 可以参考他们的建议开发应用
- <system_constraints>
- ...之前的提示内容
- <IntegrationExamples>
- <Integration name="百炼平台AI">
- // 已知存在server端的api文件 src/app/api/ai/route.ts
- // 浏览器端调用示例
- // 文本生成(非流式)
- const response = await fetch('/api/ai', {
- method: 'POST',
- headers: {
- 'Content-Type': 'application/json'
- },
- body: JSON.stringify({
- action: 'text-generation',
- data: {
- model: 'qwen-plus',
- messages: [
- {
- role: 'system',
- content: 'You are a helpful assistant.'
- },
- {
- role: 'user',
- content: '你是谁?'
- }
- ]
- }
- })
- });
- /**
- 文本生成response的数据结构如下
- {
- "choices": [
- {
- "message": {
- "role": "assistant",
- "content": ""
- },
- "finish_reason": "stop",
- "index": 0,
- "logprobs": null
- }
- ],
- "object": "chat.completion",
- "usage": {
- "prompt_tokens": 121,
- "completion_tokens": 788,
- "total_tokens": 909,
- "prompt_tokens_details": {
- "cached_tokens": 0
- }
- },
- "created": 1755147048,
- "system_fingerprint": null,
- "model": "qwen-plus",
- "id": ""
- }
- **/
- // 文本生成(流式)
- const response = await fetch('/api/ai', {
- method: 'POST',
- headers: {
- 'Content-Type': 'application/json'
- },
- body: JSON.stringify({
- action: 'text-generation',
- data: {
- model: 'qwen-plus',
- messages: [
- {
- role: 'system',
- content: 'You are a helpful assistant.'
- },
- {
- role: 'user',
- content: '你是谁?'
- }
- ],
- stream: true,
- stream_options: {
- include_usage: true
- }
- }
- })
- });
- // 处理流式响应
- if (response.body) {
- const reader = response.body.getReader();
- const decoder = new TextDecoder();
-
- while (true) {
- const { done, value } = await reader.read();
- if (done) break;
-
- const chunk = decoder.decode(value);
- // 处理每个数据块
- console.log(chunk);
- }
- }
- // 图像生成1-启动异步生成任务
- const response = await fetch('/api/ai', {
- method: 'POST',
- headers: {
- 'Content-Type': 'application/json'
- },
- body: JSON.stringify({
- action: 'image-generation',
- data: {
- model: 'wan2.2-t2i-flash',
- input: {
- prompt: '一间有着精致窗户的花店,漂亮的木质门,摆放着花朵'
- },
- parameters: {
- size: '1024*1024',
- n: 1
- }
- }
- })
- });
- const { output } = await response.json();
- const taskId = output.task_id;
- // 图像生成2-查询异步任务
- const response = await fetch('/api/ai', {
- method: 'POST',
- headers: {
- 'Content-Type': 'application/json'
- },
- body: JSON.stringify({
- action: 'get-image-task',
- data: {
- taskId: '86ecf553-d340-4e21-xxxxxxxxx'
- }
- })
- });
- const result = await response.json();
- /**
- result.output?.task_status 状态码如下:
- PENDING:任务排队中
- RUNNING:任务处理中
- SUCCEEDED:任务执行成功
- FAILED:任务执行失败
- CANCELED:任务取消成功
- UNKNOWN:任务不存在或状态未知
- 示例:
- if(result.output?.task_status === 'SUCCEEDED'){
- let imageurl = result.output.results?.[0]?.url;
- }
- **/
- // 图像理解
- const response = await fetch('/api/ai', {
- method: 'POST',
- headers: {
- 'Content-Type': 'application/json'
- },
- body: JSON.stringify({
- action: 'visual-understanding',
- data: {
- model: 'qwen-vl-max',
- messages: [
- {
- role: 'system',
- content: [
- { type: 'text', text: 'You are a helpful assistant.' }
- ]
- },
- {
- role: 'user',
- content: [
- {
- type: 'image_url',
- image_url: {
- url: '<img-url>'
- }
- },
- { type: 'text', text: '图中描绘的是什么景象?' }
- ]
- }
- ]
- }
- })
- });
- // 音频理解(音频识别)示例
- const response = await fetch('/api/ai', {
- method: 'POST',
- headers: {
- 'Content-Type': 'application/json'
- },
- body: JSON.stringify({
- action: 'audio-understanding',
- data: {
- model: 'qwen-audio-turbo-latest',
- input: {
- messages: [
- {
- role: "system",
- content: [
- {"text": "You are a helpful assistant."}
- ]
- },
- {
- role: "user",
- content: [
- {"audio": "https://dashscope.oss-cn-beijing.aliyuncs.com/audios/welcome.mp3"},
- {"text": "这段音频在说什么?"}
- ]
- },
- {
- role: "assistant",
- content: [
- {"text": "这段音频说的是:'欢迎使用阿里云'"}
- ]
- },
- {
- role: "user",
- content: [
- {"text": "介绍一下这家公司。"}
- ]
- }
- ]
- }
- }
- })
- });
- const result = await response.json();
- // 文本转语音示例(语音合成)
- const response = await fetch('/api/ai', {
- method: 'POST',
- headers: {
- 'Content-Type': 'application/json'
- },
- body: JSON.stringify({
- action: 'text-to-speech',
- data: {
- model: 'qwen-tts',
- input: {
- text: "那我来给大家推荐一款T恤,这款呢真的是超级好看,这个颜色呢很显气质,而且呢也是搭配的绝佳单品,大家可以闭眼入,真的是非常好看,对身材的包容性也很好,不管啥身材的宝宝呢,穿上去都是很好看的。推荐宝宝们下单哦。",
- voice: "Chelsie"
- }
- }
- })
- });
- const result = await response.json();
- /**
- result 返回示例
- {
- "output": {
- "finish_reason": "stop",
- "audio": {
- "expires_at": 1755191553,
- "data": "",
- "id": "",
- "url": ""
- }
- },
- "usage": {
- "input_tokens_details": {
- "text_tokens": 14
- },
- "total_tokens": 122,
- "output_tokens": 108,
- "input_tokens": 14,
- "output_tokens_details": {
- "audio_tokens": 108,
- "text_tokens": 0
- }
- },
- "request_id": ""
- }
- **/
- </Integration>
- <Integration name="AgentCraft AI">
- // 服务端 建议目录src/app/api/agentcraft/route.ts
- // 已知 AGENTCRAFT_BASE_URL , API_VERSION 和 TOKEN 需要用户输入
- import { NextResponse } from 'next/server';
- export async function POST(request: Request) {
- try {
- const { messages ,stream} = await request.json();
-
- // 调用知识库API
- // AgentCraft API Vesion 为 v1 或者 v2
- const response = await fetch({AGENTCRAFT_BASE_URL} + '/{API_VERSION}/chat/completions', {
- method: 'POST',
- headers: {
- 'accept': 'application/json',
- 'Authorization': 'Bearer <TOKEN>',
- 'Content-Type': 'application/json'
- },
- body: JSON.stringify({
- messages: [
- {
- role: "system",
- content: "你是一个有用的助手"
- },
- ...messages
- ],
- stream,
- max_tokens: 8192
- })
- });
- if (stream) {
- // 创建一个新的 Response 对象,直接转发流式响应
- return new Response(response.body, {
- status: response.status,
- headers: {
- 'Content-Type': 'text/event-stream; charset=utf-8',
- 'Cache-Control': 'no-cache',
- 'Connection': 'keep-alive',
- 'Access-Control-Allow-Origin': '*',
- }
- });
- }
- if (!response.ok) {
- throw new Error(`知识库API请求失败: ${response.status}`);
- }
- const data = await response.json();
- const content = data.choices?.[0]?.message?.content || '抱歉,我无法处理您的请求。请稍后再试。';
-
- return NextResponse.json({ content });
- } catch (error) {
- console.error('Error:', error);
- return NextResponse.json({ error: '处理请求时发生错误' }, { status: 500 });
- }
- }
- // 客户端
- const response = await fetch('/api/agentcraft', {
- method: 'POST',
- headers: {
- 'Content-Type': 'application/json'
- },
- body: JSON.stringify({
- action: 'text-generation',
- data: {
- model: 'qwen-plus',
- messages: [
- {
- role: 'system',
- content: 'You are a helpful assistant.'
- },
- {
- role: 'user',
- content: '你是谁?'
- }
- ],
- stream: true,
- stream_options: {
- include_usage: true
- }
- }
- })
- });
- // 处理流式响应
- if (response.body) {
- const reader = response.body.getReader();
- const decoder = new TextDecoder();
-
- while (true) {
- const { done, value } = await reader.read();
- if (done) break;
-
- const chunk = decoder.decode(value);
- // 处理每个数据块
- console.log(chunk);
- }
- }
-
- </Integration>
- </IntegrationExamples>
- ...之前的提示内容
- </system_constraints>
复制代码 可以看到,这里 IntegrationExamples 中写明了在客户端调用百炼 API 以及 AgentCraft AI 的示例,他们覆盖了文本生成,图片生成,声音生成,图像识别,知识库,智能体等全方位的 AI 能力,AI 可以根据示例很好的完成开发
开发态环境集成
为了减少 AI 的输出内容,降低成本,以及确保稳定的 AI 服务,系统通过应用模板内置了 AI 的 API Server,也就是在 NextJS 的后端服务中加入了提前写好的 AI API 服务(这里只是内置了百炼的 API 服务,AgentCraft 本身的服务则是服务端和客户端都需要重新生成)
- // app/api/ai/route.ts
- import { NextRequest, NextResponse } from 'next/server';
- // 定义类型
- type MessageContent = {
- type: string;
- text?: string;
- image_url?: { url: string };
- audio?: string;
- };
- type Message = {
- role: string;
- content: string | MessageContent[];
- };
- type RequestBodies = {
- 'text-generation': {
- model: string;
- messages: Message[];
- };
- 'image-generation': {
- model: string;
- input: {
- prompt: string;
- };
- parameters: {
- size: string;
- n: number;
- };
- };
- 'get-image-task': {
- taskId: string;
- };
- 'visual-understanding': {
- model: string;
- messages: Message[];
- };
- 'audio-understanding': {
- model: string;
- input: {
- messages: Message[];
- };
- };
- 'text-to-speech': {
- model: string;
- input: {
- text: string;
- voice?: string;
- };
- };
- };
- // API端点映射
- const API_ENDPOINTS = {
- 'text-generation': 'https://dashscope.aliyuncs.com/compatible-mode/v1/chat/completions',
- 'image-generation': 'https://dashscope.aliyuncs.com/api/v1/services/aigc/text2image/image-synthesis',
- 'get-image-task': (taskId: string) => `https://dashscope.aliyuncs.com/api/v1/tasks/${taskId}`,
- 'visual-understanding': 'https://dashscope.aliyuncs.com/compatible-mode/v1/chat/completions',
- 'audio-understanding': 'https://dashscope.aliyuncs.com/api/v1/services/aigc/multimodal-generation/generation',
- 'text-to-speech': 'https://dashscope.aliyuncs.com/api/v1/services/aigc/multimodal-generation/generation'
- };
- // 请求方法映射
- const REQUEST_METHODS = {
- 'text-generation': 'POST',
- 'image-generation': 'POST',
- 'get-image-task': 'GET',
- 'visual-understanding': 'POST',
- 'audio-understanding': 'POST',
- 'text-to-speech': 'POST'
- };
- // 是否需要异步头
- const ASYNC_HEADERS = {
- 'image-generation': true
- };
- export async function POST(req: NextRequest) {
- const { action, data } = await req.json();
-
- // 检查API密钥
- const apiKey = process.env.DASHSCOPE_API_KEY;
- if (!apiKey) {
- return NextResponse.json({ error: 'DASHSCOPE_API_KEY is not configured' }, { status: 500 });
- }
- // 验证action
- if (!(action in API_ENDPOINTS)) {
- return NextResponse.json({ error: 'Invalid action specified' }, { status: 400 });
- }
- try {
- // 特殊处理get-image-task,因为它需要taskId参数
- const url = action === 'get-image-task'
- ? API_ENDPOINTS[action](data.taskId)
- : API_ENDPOINTS[action];
-
- // 验证taskId
- if (action === 'get-image-task' && !data.taskId) {
- return NextResponse.json({ error: 'Task ID is required' }, { status: 400 });
- }
- // 构建请求头
- const headers: Record<string, string> = {
- 'Authorization': `Bearer ${apiKey}`,
- 'Content-Type': 'application/json'
- };
-
- // 添加异步头(如果需要)
- if (ASYNC_HEADERS[action as keyof typeof ASYNC_HEADERS]) {
- headers['X-DashScope-Async'] = 'enable';
- }
- // 构建请求配置
- const config: RequestInit = {
- method: REQUEST_METHODS[action],
- headers
- };
- // 添加请求体(GET请求不需要)
- if (REQUEST_METHODS[action] === 'POST') {
- config.body = JSON.stringify(data);
- }
- // 发送请求
- const response = await fetch(url, config);
- // 处理流式响应
- if (action === 'text-generation' && data.stream) {
- // 创建一个新的 Response 对象,直接转发流式响应
- return new Response(response.body, {
- status: response.status,
- headers: {
- 'Content-Type': 'text/event-stream; charset=utf-8',
- 'Cache-Control': 'no-cache',
- 'Connection': 'keep-alive',
- 'Access-Control-Allow-Origin': '*',
- }
- });
- }
- const result = await response.json();
-
- return NextResponse.json(result, { status: response.status });
- } catch (error) {
- console.error('DashScope API error:', error);
- return NextResponse.json({ error: 'Internal server error' }, { status: 500 });
- }
- }
复制代码 对于 AI 应用,还有一个比较重要的东西,就是 API 秘钥。本方案中,API 秘钥是通过环境变量的方式从上层服务注入,而不是明文写到系统,因此更加安全。- //...
- else if (shellCommand.startsWith('npm run dev')) {
- const currentPid = process.pid;
- await checkAndKillPort(PORT, currentPid);
- const childProcess: any = spawn('npm', ['run', 'dev'], {
- cwd: workdir,
- stdio: ['ignore', 'pipe', 'pipe'],
- detached: true, // 使子进程在父进程退出后继续运行
- env: {
- ...process.env,
- PATH: process.env.PATH,
- NODE_ENV: 'development', // 明确设置开发环境
- VITE_USER_NODE_ENV: 'development'
- },
- uid,
- gid
- });
- // ....
复制代码 生产态环境集成
因为在开发态的时候集成 AI 的代码以及客户端的调用代码都已经准备完毕,发布到生产环境,只是提取开发态的环境变量一并部署到服务器上即可。
构建的过程中会生成 s.yaml, 将整个生成的 AI 应用进行打包上传- const sYamlContent = `edition: 3.0.0
- name: mayama_ai_generated_app
- vars:
- region: '${process.env.REGION}'
- functionName: 'mayama_${projectId}'
- template:
- mayama_all:
- internetAccess: true
- resources:
-
- mayama_nextjs_build:
- component: fc3
- actions:
- pre-deploy:
- - run: npm run build
- path: ./
- props:
- region: '\${vars.region}'
- description: 应用
- timeout: 600
- diskSize: 512
- customRuntimeConfig:
- port: 3000
- command:
- - bootstrap
- layers:
- - acs:fc:\${vars.region}:official:layers/Nodejs20/versions/1
- - acs:fc:\${vars.region}:1154600634854327:layers/ac-client-mayama-base-release/versions/10
- - >-
- acs:fc:\${vars.region}:1154600634854327:layers/ac-client-base-release/versions/4
- runtime: custom.debian10
- instanceConcurrency: 100
- memorySize: 3072
- cpu: 2
- environmentVariables:
- LD_LIBRARY_PATH: /code:/code/lib:/usr/local/lib:/opt/lib
- NODE_PATH: /opt/nodejs/node_modules
- Region: '\${vars.region}'
- DASHSCOPE_API_KEY: ${process.env.DASHSCOPE_API_KEY || ''}
- NEXT_PUBLIC_SUPABASE_URL: ${NEXT_PUBLIC_SUPABASE_URL}
- NEXT_PUBLIC_SUPABASE_ANON_KEY: ${NEXT_PUBLIC_SUPABASE_ANON_KEY}
- PATH: >-
- /opt/nodejs20/bin:/usr/local/bin/apache-maven/bin:/usr/local/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/local/ruby/bin:/opt/bin:/code:/code/bin:/opt/nodejs/node_modules/.bin
- functionName: \${vars.functionName}
- code: ./
- triggers:
- - description: ''
- qualifier: LATEST
- triggerName: defaultTrigger
- triggerType: http
- triggerConfig:
- methods:
- - GET
- - POST
- - PUT
- - DELETE
- authType: anonymous
- disableURLInternet: false
- customDomain:
- protocol: "HTTP"
- route:
- path: "/*"
- qualifier: "LATEST"
- domainName: auto
- extend:
- name: mayama_all
-
- `;
- await fs.writeFile(sYamlPath, sYamlContent, 'utf-8');
- console.log(`✅ 已创建 s.yaml 配置文件`);
复制代码 VibeCoding 的技巧
了解系统的设计可以掌握系统的应用边界,知晓什么时候可以强化提示让 AI 系统更好的完成生产任务。这里有些小技巧。
一、项目唯一ID
当 AI 第一次将项目信息输出的时候,后续都应该围绕这里的 ID 进行持续的迭代,因为系统构建真实的应用文件是以这个 ID 为唯一值,如果你发现 ID 变了,那就意味着系统重新生成了一个项目,无法延续你之前的项目。 此时可以跟系统说“请在项目 ID 是 xxxx 的项目上修改”,这样就保持了项目持续迭代的一致性。
这里也建议一个会话对应一个项目,防止生成混淆。
二、一些必要的交流术语
绝大部分情况下,你使用自然语言表达自己的需求要求 AI 满足即可,但某些情况下,需要给他一些专业的软件开发术语,可以让他修改的更加明确,比如上述示例,使用 xxxx api 完成开发(复制的是一个 curl 的请求),再比如构建应用视觉的时候,可以输入 “请把页面上的卡片元素进行垂直/水平居中”,请使用 xxx 的 json 数据进行数据模拟等等。
三、异常情况处理
AI 编程结果不一定是一帆风顺的,系统内置了错误提示的效果,因此当遇到错误的时候最简单直接的办法就是直接粘贴复制,让 AI 自己看错误去修改。
除了异常,系统还会把生成的应用本身,以及多轮对话等上下文都一并传入给 AI,全面的上下文可以更好的让 AI 帮助我们解决问题。
四、解决不了的死循环
AI 可能会陷入某种死循环,怎么问问题都解决不了,此时你可以要求他换个思路,或者我们换一个问话方式,看看是否可以解决。
未来展望
随着 VibeCoding 解决方案的持续进化,我们正朝着全民开发者时代迈进,
- 国内开放平台的登录:使用支付宝,微信等登录系统直接让自己生成的应用对外可服务
- 小程序/移动应用:扩展应用类型,如支持小程序或者移动应用的自然语言编程方案
- Agentic 应用:支持更复杂的 Agentic 工作流,多模态应用
上手体验
访问阿里云 Function AI控制台参考《全球首个搭载Kimi-K2&Qwen3-Coder的Serverless架构VibeCoding解决方案重磅来袭!》内容教程进行部署使用。
更多内容关注 Serverless 微信公众号(ID:serverlessdevs),汇集 Serverless 技术最全内容,定期举办 Serverless 活动、直播,用户最佳实践。
来源:豆瓜网用户自行投稿发布,如果侵权,请联系站长删除 |