一、技術背景與需求分析
? ? ? ? 我們日常在使用AI的時候一定都上傳過文件,AI會根據用戶上傳的文件內容結合用戶的請求進行分析,給出用戶解答。但是這是怎么實現的呢?在我們開發自己的大模型應用時肯定是不可避免的要思考這個問題,今天我會將從文件上傳開始到大模型給出分析的整個流程進行講解
二、核心技術實現路徑
? ? ? ? 在這里我先將整體的流程說一下:
前端文件上傳 → 服務端接收文件 → 解析文件 → 生成唯一Id → 將文件存儲(id:content)| |—————————————————存儲id←———————————————↓
用戶發送請求 → 用戶信息+文件id → 服務端接收請求 → 根據id獲取文件內容 → 拼接用戶消息和文件內容↓大模型分析↓返回響應
1.文件上傳于預處理
? ? ? ? 文件上傳的前端部分我不再進行講解,但是需要說明的是,在前端需要加上對文件的約束和校驗,比如文件大小、文件格式等。
? ? ? ? 后端的編寫上首先需要準備一個接口去接收文件。
在這個接口中實現的效果就是流程圖中第一行的功能
@RequestMapping(value = "/upload", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)public UploadFileResultDto upload(@RequestPart("filedata") MultipartFile multipartFile) throws IOException {if (multipartFile.getSize() > 1024 * 1024 * 10){throw new RuntimeException("文件大小不能超過10M");}//解析文件String content = fileParseService.parse(multipartFile);//唯一idString fileId = UUID.randomUUID().toString();//存儲文件memoryStorage.save(fileId, content);UploadFileResultDto uploadFileResultDto = new UploadFileResultDto();uploadFileResultDto.setFileId(fileId);return uploadFileResultDto;}
?解析文件類,這個的最佳實踐是:通過一個工廠類檢測文件類型,將不同文件類型的文件交給不同的解析工具類執行
我這里僅舉一個例子,只包含解析txt文件的條件
public interface FileParseService {String parse(MultipartFile file);
}
?中專工廠
@Service
public class FileParseServiceImpl implements FileParseService {@Overridepublic String parse(MultipartFile file) {//根據文件類型解析文件try {if (Objects.equals(file.getContentType(), "text/plain")){return new TxtFileParser().parse(file);}} catch (Exception e) {throw new RuntimeException(e);}return null;}
}
解析工具類
@Component
public class TxtFileParser {public String parse(MultipartFile file) throws Exception {StringBuilder Totalline;try (BufferedReader reader = new BufferedReader(new InputStreamReader(file.getInputStream()))) {Totalline = new StringBuilder();Totalline.append("文件【").append(file.getOriginalFilename()).append("】:\n");String line;while ((line = reader.readLine()) != null) {Totalline.append(line);}}return Totalline.toString();}
}
當響應結束后,返回文件的內容,然后在controller中生成一個UUID
以UUID作為key文件內作為value,因為最終是要將文件信息以Map的格式保存
創建一個存儲類,用于存儲文件信息。
@Component
public class MemoryStorage {//文件存儲private static final ConcurrentHashMap<String,String> storage = new ConcurrentHashMap<>();//存儲文件public void save(String fileId, String content) {storage.put(fileId, content);System.out.println("文件存儲成功"+fileId);}//獲取文件public String get(String fileId) {return storage.get(fileId);}//刪除文件public void remove(String fileId) {storage.remove(fileId);System.out.println("文件刪除成功"+fileId);}//清空所有文件public void clear() {storage.clear();System.out.println("文件清空成功");}
}
執行完這些后,文件的上傳工作已經完成
此時前端會收到該文件的唯一Id,其會對這個id進行保存。
當用戶發送消息時,會帶著文件id的列表一并發送到服務器。
請求體:
@Data
public class GetRequest {//消息private String message;.....其余屬性//文件列表private List<String> fileIds;
如果文件id列表不為空,服務端會從存儲類中取得對應的文件內容
然后將文件內容和用戶消息進行拼接
//用戶消息
String userMessage = request.getMessage();
//文件內容->將用戶消息和文件內容進行拼接
if (request.getFileIds() != null){userMessage = formatFile(request.getFileIds()) + "【用戶消息】:\n"+userMessage;
}
@Autowiredprivate MemoryStorage memoryStorage;public String formatFile(List<String> fileIds){if (fileIds == null){return null;}StringBuilder fileContent = new StringBuilder();for (String fileId : fileIds){String content = memoryStorage.get(fileId);fileContent.append(content).append("\n");}return fileContent.toString();}
最終模型收到的用戶消息類似于這樣的格式:
文件【xxx】:...【用戶消息】:...
使得模型能夠區分文件內容和具體的指令并進行分析
這是我的實驗效果
?
三.優化路線
?模型對文件進行分析的操作,大致還會有以下的優化步驟
1.數據脫敏:對敏感信息進行屏蔽再進行分析+盡量在用戶本地解析,當然這是針對商業化的需求
2.加密傳輸:對一些重要的信息和文件,在進行網絡傳輸時需要對其進行加密操作
3.分塊傳輸:一些大的文件一次性無法直接傳輸,需要進行分塊
4.文件處理:在本文中我只介紹了文本文件的處理,這種是可以直接進行讀取的,其他類型的文件? ? ? ? ? ? ? ? ? ? ? ?例如PDF、EXCEL等還需要進行拓展工具類。甚至是圖片、視頻、音頻等都需要根? ? ? ? ? ? ? ? ? ? ? ? ?據不同的情況和技術選型選擇不同的處理方案
開源項目參考
? ? ? ? 以上代碼和技術實現都是根據我的開源項目進行的展示,大家需要詳細的了解的可以訪問下載我的項目,跪求點個star!!!
??Local_Helper: 支持本地大模型的可視化應用