最近大家都在玩LLM,我也凑了热闹,简单实现了一个本地LLM应用,分享给大家,百分百可以用哦~^ - ^
先介绍下我使用的三种工具:
- Ollama:一个免费的开源框架,可以让大模型很容易的运行在本地电脑上
- FastAPI:是一个用于构建 API 的现代、快速(高性能)的 web 框架,使用 Python 并基于标准的 Python 类型提示
- React:通过组件来构建用户界面的库
简单来说就类似于LLM(数据库)+FastAPI(服务端)+React(前端)
开始搭建
1、下载Ollama之后使用Ollama完成大模型的本地下载和的运行
ollama run llama3:8b
这里我下载了最新的llama3:8b,电脑配置不高的话10b以内可以无痛运行,当然啦你也可以多下几个大模型,对比一下,我还下载了qwen,对比下来同一模型越大越聪慧,国内模型对中文支持度普遍好一点。
2、模型运行之后就可以调用了
curl http://localhost:11434/api/generate -d '{
"model": "llama3:8b",
"prompt": "Why is the sky blue?",
"stream": false
}'
3、新建一个python项目,实现代码如下:
import uvicorn
from fastapi import FastAPI, Request, HTTPException
from fastapi.middleware.cors import CORSMiddleware
from pydantic import BaseModel
import json
import requests
from sse_starlette.sse import EventSourceResponse
import asyncio
import aiohttp
app = FastAPI(debug=True)
origins = [
"http://localhost",
# 输入自己前端项目的地址
]
# 设置跨域
app.add_middleware(
CORSMiddleware,
allow_origins=origins,
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
)
urls = ["http://localhost:11434/api/generate"]
llm_list = [ {'label': 'qwen:latest', "value": 'qwen:latest'},
{'label': 'llama3:8b', "value": 'llama3:8b'}, ]
# 获取模型列表
@app.get("/llm/list")
def read_llm(model: str = 'qwen:latest'):
return {"data": llm_list}
# 这是一个异步生成器函数,它发送请求到 Ollama,并逐行读取响应内容,生成事件流。
async def stream_ollama_response(model_name, prompt):
if model_name:
url = urls[0]
payload = {
"model": model_name,
"prompt": prompt,
"stream": True
}
async with aiohttp.ClientSession() as session:
async with session.post(url, json=payload) as response:
async for line in response.content:
if line:
data = line.decode('utf-8').strip()
if data:
yield {"event": "message", "data": json.loads(data)["response"]}
# 开始对话,接收 model_name 和 prompt 参数。它调用 event_generator 函数,启动与 Ollama 的交互,并通过 EventSourceResponse 返回事件流
@app.get("/chat")
async def generate(request: Request, model_name: str = 'qwen:latest',
prompt: str = '请用中文介绍下中国古代四大名著之一的《红楼梦》'):
async def event_generator():
async for event in stream_ollama_response(model_name, prompt):
yield event
if await request.is_disconnected():
break
return EventSourceResponse(event_generator())
if __name__ == '__main__':
uvicorn.run(app="app", host="127.0.0.1", port=8000, reload=True)
这是用SSE形式实现流式输出的demo,下一篇我再讲讲如何用WebSocket实现。
4、新建一个react项目,我用了antd大礼包+@microsoft/fetch-event-source这个微软的sse插件实现,代码如下:
import { Input, Dropdown, Select, Form, Button, Space } from 'antd';
import { useEffect, useState } from 'react';
import { getList, chat } from './service';
import { useRequest } from '@umijs/max';
import { fetchEventSource } from '@microsoft/fetch-event-source';
const { TextArea } = Input;
# 不能走代理哦,走了代理流式就失效了,?- ?
export const getHost = () => {
const isDev = process.env.NODE_ENV === 'development';
if (isDev) {
return 'http://127.0.0.1:8000';
} else {
return '';
}
};
export default () => {
const [form] = Form.useForm();
const { data = [] } = useRequest(getList);
const [value, setValue] = useState('');
const [start, setStart] = useState(null);
const [end, setEnd] = useState(null);
const [selected, setSelected] = useState(false);
const [controller, setController] = useState(new AbortController());
const sharedProps = {
style: { width: '100%' },
autoSize: { minRows: 3, maxRows: 20 },
onChange: (e) => {
setValue(e.target.value);
setStart(e.target.selectionStart);
},
onClick: (e) => {
setStart(e.target.selectionStart);
},
onSelect: (e) => {
setStart(e.target.selectionStart);
setEnd(e.target.selectionEnd);
setSelected(e.target.value.substring(e.target.selectionStart, e.target.selectionEnd));
},
};
const items = [
{
label: '重写这句话',
key: '3',
},
{
label: '把这句话翻译成中文',
key: '4',
},
];
const menuClick = ({ key }) => {
switch (key) {
case '3':
return reWrite();
case '4':
return reWrite('zh-CN');
}
};
const reWrite = async (type) => {
if (!selected) {
return;
}
setValue(value.slice(0, start) + '重写中。。。' + value.slice(end));
const res = await chat({
model: form.getFieldValue('model'),
prompt: type
? `${selected}”把“”中的这句话或单词翻译成中文,返回不要带格式,直接返回翻译结果`
: selected,
});
setValue(value.slice(0, start) + res.data + value.slice(end));
};
# 获取数据流
const fetchData = async (url) => {
await fetchEventSource(url, {
method: 'GET',
signal: controller.signal,
onopen(res) {
if (res.ok && res.status === 200) {
console.log('Connection made ', res);
} else if (res.status >= 400 && res.status < 500 && res.status !== 429) {
errorHandler(res);
console.log('Client side error ', res);
}
},
onmessage(event) {
console.log(event);
setValue((data) => [...data, event.data].join(''));
},
onclose() {
console.log('Connection closed by the server');
},
onerror(err) {
console.log('There was an error from server', err);
},
});
};
const onFinish = (values) => {
fetchData(`${getHost()}/chat?model_name=${values.model_name}&prompt=${values.prompt}`);
};
return (
<div>
<Form onFinish={onFinish} form={form}>
<Form.Item name="model_name" label="模型">
<Select style={{ width: 200 }} options={[...data]} />
</Form.Item>
<Form.Item name="prompt" label="提问">
<Input />
</Form.Item>
<Form.Item>
<Space>
<Button type="primary" htmlType="submit">
提交
</Button>
<Button onClick={() => controller.abort()}>
暂停
</Button>
</Space>
</Form.Item>
</Form>
<Dropdown menu={{ items, onClick: menuClick }} trigger={['contextMenu']}>
<TextArea value={value} {...sharedProps} />
</Dropdown>
</div>
);
};
界面比较简陋,大家随便看一下:
前端代码还加了些小功能,比如右键支持某句话的替换和翻译,因为用了input,所以可以获取光标的位置从而把文本插入或者替换选中文本。不过还有个弊端就是没办法支持markdown输出了,这个问题暂时还不知道怎么解决,要么再添加个预览模式。
最后的最后
感谢你们的阅读和喜欢,我收藏了很多技术干货,可以共享给喜欢我文章的朋友们,如果你肯花时间沉下心去学习,它们一定能帮到你。
因为这个行业不同于其他行业,知识体系实在是过于庞大,知识更新也非常快。作为一个普通人,无法全部学完,所以我们在提升技术的时候,首先需要明确一个目标,然后制定好完整的计划,同时找到好的学习方法,这样才能更快的提升自己。
这份完整版的大模型 AI 学习资料已经上传CSDN,朋友们如果需要可以微信扫描下方CSDN官方认证二维码免费领取【保证100%免费
】
一、全套AGI大模型学习路线
AI大模型时代的学习之旅:从基础到前沿,掌握人工智能的核心技能!
二、640套AI大模型报告合集
这套包含640份报告的合集,涵盖了AI大模型的理论研究、技术实现、行业应用等多个方面。无论您是科研人员、工程师,还是对AI大模型感兴趣的爱好者,这套报告合集都将为您提供宝贵的信息和启示。
三、AI大模型经典PDF籍
随着人工智能技术的飞速发展,AI大模型已经成为了当今科技领域的一大热点。这些大型预训练模型,如GPT-3、BERT、XLNet等,以其强大的语言理解和生成能力,正在改变我们对人工智能的认识。 那以下这些PDF籍就是非常不错的学习资源。
四、AI大模型商业化落地方案
五、面试资料
我们学习AI大模型必然是想找到高薪的工作,下面这些面试题都是总结当前最新、最热、最高频的面试题,并且每道题都有详细的答案,面试前刷完这套面试题资料,小小offer,不在话下。
这份完整版的大模型 AI 学习资料已经上传CSDN,朋友们如果需要可以微信扫描下方CSDN官方认证二维码免费领取【保证100%免费
】