「极简」LLM大模型应用开发

180 阅读12分钟

什么是LLM大模型应用

LLM大模型应用可以说是当前最火热的应用话题了,那么什么是LLM大模型应用?

LLM大模型应用就是一种基于LLM大模型开发出来的应用。其本质是利用LLM大模型能力,在这一基础上开发出来的应用。(一本正经水字数)

那么什么又是LLM大模型?

LLM大模型,全称Large Language Model:大语言模型。这是一种能够实现语义理解并产生相应推理的机器学习模型。它是由语言模型(LM)演化而来,用大白话说:LLM是参数非常多的LM。

从算法上来说,实现一个LLM大模型是一件非常困难的事情,从算法本身到数据准备,从硬件购买到真正训练,每一个环节都散发着「困难」的气息。但从原理上来说LLM大模型它并不困难,甚至还有点简单。因为LM核心原理是根据已有文字推测下一个文字。如果将预测算法抽象成一个predict函数,那么在这一过程就可以简化成以下简单的代码调用。

下一个字=predict(问题)
再下一个字=predict(问题+下一个字)

不断循环这一过程,就能得到一段可以用于回答问题的文本。

基于上述原理,我们可以简单做出一个结论:LLM大模型能够从给定的文本基础上产生文本。 不考虑流式响应过程,那么我们也可以将LLM大模型简单抽象成一行代码调用:

answer = LLM(question)

当然,LLM大模型实际上要比这一行代码复杂得多,但我们的标题是「极简」,因此这篇文章并不会涉及过于深度的原理。

大模型应用开发原理

由于目前聊天框形式的LLM大模型应用非常多,因此很多人可能以为只有聊天形式才可以做LLM大模型应用。

但实际上的LLM大模型应用可以是五花八门的,可以是聊天,也可以是做报表、画图、生成ppt等各种形式。甚至我们可以在自己的应用中嵌入AI能力实现一些更有意思的事情,例如:我们可以对手机说要买一张去上海的机票,手机自动识别人类的意图并成功购买需要的机票。在这个过程中甚至还可以同步开启多个APP进行比价,这些操作可以全都由AI识别并做出相应的反应。

虽然听上去好像很复杂,但最本质的原理其实如同LM一样简单:LLM大模型应用开发最为核心的原理在于提示词工程。以下是任何一个LLM大模型应用都躲不掉的基本流程:

graph LR
prompt[组装提示词] --> LLM --> response[处理响应结果]

乍一看好像画了个寂寞,但这确实是LLM大模型应用最底层且最核心的流程图。

以DeepSeek聊天网页为例,用户提出问题,这个问题最终会被合并到提示词中然后交给LLM大模型推理。LLM大模型将得到的结果再返回给用户,于是用户得到了最终想要的结果。

虽然从原理上来说这一过程非常简单,但从真实项目角度来说,LLM大模型应用远比这个过程复杂得多。实际开发中我们为了提升LLM大模型的效果,需要尽可能完善提示词的方方面面,从而获得相对较好的大模型响应。同时也需要对LLM大模型输出的文本进行不同的格式处理才能达到比较舒适的用户体验。

大模型应用缺陷

如今已经是2025年了,对于大模型的缺陷应该很多人都有听说了。总的来说大模型有几个比较致命的缺陷,这些缺陷会让使用者对LLM大模型应用产生相当程度的不信任感。

幻觉

大模型输出有时候看似一本正经,但很有可能是胡说八道。他所引用的论据有可能是不存在的,他所编撰的事实也可能是胡编乱造的。

这是大模型最为让人诟病的一点,很多人一开始使用LLM大模型应用的时候是非常信任的,因为大模型输出的文本看上去有理有据,也符合人类语言的基本语法,但不要忘了我们之前提到的LM核心原理:

下一个字=predict(问题)
再下一个字=predict(问题+下一个字)

在这种推理公式下,我们可以立即得到一个结论:幻觉无法避免。因为你永远不知道下一个字是从哪里来的,它可能是基于统计词频产生的,也可能是通过概率产生的,总之它不是由真正的思考产生的。

数据库时效

大模型通过大量数据训练而成,这些数据通常有时效性。一旦训练结束,大模型的知识就定格在结束训练的那一天。例如大模型训练数据都是2025年3月之前的,我提问:2025年4月发生了什么?

大模型并不会真正推理出这句话的意图,它通过预测算法生成了一个看似合情合理的答案,但如果你足够敏锐,你会第一时间发现这些答案都是不正确的。

上下文长度

上下文长度也是目前来说比较让人在意的一点,以Deepseek为例,目前deepseek v3的上下文长度是64k个token,根据官方文档的计算,一个中文字符大约是0.6个token,因此64k的上下文大约可以塞进去10万个字。

看上去这个上下文长度好像还不错,但实际上这个数字对于一些复杂需求来说就显得有点太少了,比如我现在想写一篇一百万字左右的网络小说,而大模型上下文长度最多只能支持10万字左右,那么等我写到30万字的时候,大模型甚至会忘了前面20万字中的剧情和人物。

实战:一个流程图绘制工具

为了尽可能打开思路,这里的应用形式不会使用聊天框。

同时为了贯彻「极简」,一切的一切将会由一个fetch函数发起,慢慢扩充成一整个简单应用。本案例不会引入LangChain等框架,也不会使用任何第三方库,从而降低阅读的心智负担。

前文说过,一个最简单的LLM大模型应用有三个部分:构建提示词,传给LLM大模型,处理返回值。

提示词

这里先简单申明一下,LLM大模型只能处理文本,它不是多模态模型。因此实际上它并不能输出真正的图片。

但卑鄙的人类总能想到突破口,虽然直接生成图片我们并不能做到,但是文字类信息中也有不少可以渲染成图片的东西,例如:svg、mermaid代码、html等各种结构化文本。

于是到这里思路就能打开了,先简单写一个用于生成mermaid代码的提示词:

### 角色定义
作为“Mermaid 专业流程图生成器”,你的核心职责是将自然语言描述的流程转换为符合 Mermaid.js 语法的代码。你擅长复杂逻辑分析、多级节点排布和语法验证。技能涵盖:
- 精准识别流程逻辑关系
- 自动适配 TD/LR/RL 等 8 种图表方向
- 支持三级嵌套子图

### 任务框架
对于需要将业务流程可视化的开发者/产品经理,请将用户提供的流程描述转换为结构化的 Mermaid 代码。要求:
1. 必须包含三层节点层次结构,可通过缩进或子图实现(见下方示例)
2. 节点样式规范:
- 系统操作节点:蓝色矩形 `id1[content]`
- 异常处理节点:红色菱形 `id2{{content}}`
- 起始/结束节点:绿色圆角矩形 `id3(content)`
3. 连接线类型强制规范:
- 实线:`-->`
- 虚线:`-.->`
- 粗线:`==>`
- 点划线:`-.-.->`

### 语法约束
```mermaid
graph TD
    Direction declaration (必须是第一行)
    subgraph 用户登录流程
        direction TB
        A((start)) --> B[输入凭证]
        B --> C{{验证通过?}}
        C -->|yes| D[[系统主页]]
        C -->|no| E{{异常处理}}
        E -->|retry| B
        E -->|exit| F(END)
        style A fill:#4CAF50,stroke:#333
        style E fill:#FF0000,stroke:#333
    end
```
### 格式约束
1. 请严格遵循以下格式返回
```mermaid
{{mermaid code}}
```
2. 仅返回mermaid代码

### 用户输入
=====
{input}
=====

### 输出

到这里这个提示词就算是写完了,整个提示词大部分用于约束LLM大模型输出的内容与格式,在提示词最后使用一个{input}作为用户输入的提问占位符,最终我们会将{input}替换成需要转换成流程图的实际文本。

请求大模型

请求大模型这里使用前端原生fetchapi,因为足够简单且好用。即便是没有前端基础的人也能轻易读懂代码含义。

// 定义一个用于获取大模型返回值的函数
async function getLLMResponse(userInput){
    // 将提示词中的占位符替换成最终需要转换成流程图的文本
    const inputText = prompt.replace('{input}', userInput);
    return await fetch('https://api.qnaigc.com/v1/chat/completions', {
        method: 'POST',
        headers: {
            'Content-Type': 'application/json',
            'Authorization': 'Bearer 你的token'
        },
        body: JSON.stringify({
            messages: [{"role": "user", "content": userInput}],
            stream: false,
            model: "deepseek-v3-0324"
        })
    })
    // 返回值是json格式,使用fetch api自动转换json
    .then(res => res.json())
    .then(data => {
        // 大模型返回的数据结构有几个字段
        // 其中choice字段中保存了大模型返回的数据
        // 如果使用流形式,数据保存在chunk.choices[0].delta.content中
        // 具体格式需要参考对应大模型提供商的文档,这里的例子使用的是七牛云
        return data.choices[0].message.content 
    })
}

处理输出结果

走完上面两步,我们就可以得到一个用于渲染的mermaid代码。正常情况下,我们需要写一个前端用于渲染mermaid流程图,但是这并不是这篇文章的核心。

为了贯彻「极简」,直接将代码复制到在线编辑器中就可以看到最终显示的结果。

代码合并

前面都是一些碎片化的代码,最终我们需要合并成一个nodejs可执行的js文件。

const prompt = `
### 角色定义
作为“Mermaid 专业流程图生成器”,你的核心职责是将自然语言描述的流程转换为符合 Mermaid.js 语法的代码。你擅长复杂逻辑分析、多级节点排布和语法验证。技能涵盖:
- 精准识别流程逻辑关系
- 自动适配 TD/LR/RL 等 8 种图表方向
- 支持三级嵌套子图

### 任务框架
对于需要将业务流程可视化的开发者/产品经理,请将用户提供的流程描述转换为结构化的 Mermaid 代码。要求:
1. 必须包含三层节点层次结构,可通过缩进或子图实现(见下方示例)
2. 节点样式规范:
- 系统操作节点:蓝色矩形 \`id1[content]\`
- 异常处理节点:红色菱形 \`id2{{content}}\`
- 起始/结束节点:绿色圆角矩形 \`id3(content)\`
3. 连接线类型强制规范:
- 实线:\`-->\`
- 虚线:\`-.->\`
- 粗线:\`==>\`
- 点划线:\`-.-.->\`

### 语法约束
\`\`\`mermaid
graph TD
    Direction declaration (必须是第一行)
    subgraph 用户登录流程
        direction TB
        A((start)) --> B[输入凭证]
        B --> C{{验证通过?}}
        C -->|yes| D[[系统主页]]
        C -->|no| E{{异常处理}}
        E -->|retry| B
        E -->|exit| F(END)
        style A fill:#4CAF50,stroke:#333
        style E fill:#FF0000,stroke:#333
    end
\`\`\`
### 格式约束
1. 请严格遵循以下格式返回
\`\`\`mermaid
{{mermaid code}}
\`\`\`
2. 仅返回mermaid代码

### 用户输入
=====
{input}
=====

### 输出
`;

// 定义一个用于获取大模型返回值的函数
async function getLLMResponse(userInput){
    // 将提示词中的占位符替换成最终需要转换成流程图的文本
    const inputText = prompt.replace('{input}', userInput);
    return await fetch('https://api.qnaigc.com/v1/chat/completions', {
        method: 'POST',
        headers: {
            'Content-Type': 'application/json',
            'Authorization': 'Bearer token'
        },
        body: JSON.stringify({
            messages: [{"role": "user", "content": inputText}],
            stream: false,
            model: "deepseek-v3-0324"
        })
    })
        // 返回值是json格式,使用fetch api自动转换json
        .then(res => res.json())
        .then(data => {
            // 大模型返回的数据结构有几个字段
            // 其中choice字段中保存了大模型返回的数据
            // 如果使用流形式,数据保存在chunk.choices[0].delta.content中
            // 具体格式需要参考对应大模型提供商的文档,这里的例子使用的是七牛云
            return data.choices[0].message.content
        })
}

getLLMResponse("蛋炒饭的一般步骤是:1. 打蛋。2. 炒蛋。3. 炒饭。4. 混合。5. 上菜。").then(res => {
    console.log(res)
})

了解nodejs的同学可以复制到js文件中使用node直接运行,如果不了解nodejs也没关系,直接复制源码,打开chrome浏览器,F12打开开发者工具,将代码复制到控制台直接运行也可以得到正确结果。

上面的例子产生的mermaid代码最终会被渲染成以下图片:

image.png

总结

大模型应用开发从原理上来说其实并不复杂,与传统应用开发相比,大模型应用开发无非多了一个组装提示词的过程。新技术的出现总是因为未知而让人心生畏惧,但这并不会难到我们技术人,多多尝试就会发现其实也就那么一回事。

另外提一嘴,本次案例使用七牛云的deepseek v3大模型,虽然它有非常多的缺点,不仅速度慢,还会给限流。目前使用下来基本上每天用到50w token后就会请求超时。但架不住它确实便宜,目前新用户1000w token的价格是3块多,并且新用户注册就送100w token,感兴趣的小伙伴可以点七牛云注册一下薅一波羊毛。

我是「锐编程」,一位喜欢折腾的前端程序员。目前正在折腾的方向是大模型应用开发、知识分享。如果您也喜欢折腾,欢迎添加「锐编程」公众号。