萧恺 2025-03-28 08:31 浙江
作者分享了跟 AI 协作的一些经验,使用中如何对 AI 输入和反馈,经过磨合后,工作效率会大大提升。
这是2025年的第27篇文章
( 本文阅读时间:15分钟 )
01
前言
02
工具选择
2.1 基础用法
<file_map>/Users/xiaohansong/IdeaProjects/medigw└── app└── service└── src└── main└── java└── com└── xxx└── medigw└── core└── service└── ocr└── Doc2xOcrService.java<Referenced APIs>Path: /Users/xiaohansong/IdeaProjects/medigw/app/service/src/main/java/com/xxx/medigw/core/service/ocr/ParserProgress.java---Classes:Class: ParserProgressMethods:- public Integer getTotalProgress() {- public void setTotalProgress(Integer totalProgress) {- public Map<String, Integer> getProgressMap() {- public void setProgressMap(Map<String, Integer> progressMap) {- public String getStatus() {- public void setStatus(String status) {- public Map<String, String> getErrorMap() {- public void setErrorMap(Map<String, String> errorMap) {---</Referenced APIs></file_map><file_contents>File: app/service/src/main/java/com/medigw/core/service/ocr/Doc2xOcrService.java```javapackage com.xxx.medigw.core.service.ocr;import com.alibaba.fastjson.JSON;import com.alibaba.fastjson.TypeReference;import com.xxx.medigw.common.utils.LoggerUtil;import com.xxx.medigw.core.service.oss.Doc2xConfig;import com.xxx.medigw.core.service.oss.OSSService;import org.apache.http.client.fluent.Request;import org.apache.http.client.utils.URIBuilder;import org.apache.http.entity.ContentType;import org.slf4j.Logger;import org.slf4j.LoggerFactory;import java.util.HashMap;import java.util.Map;public class Doc2xOcrService {private final static Logger LOGGER = LoggerFactory.getLogger(Doc2xOcrService.class);/*** doc2x解析服务endpoint*/private static final String OSS_BUCKET_NAME = "dataset";private static final String DOC2X_TARGET_BASE_DIR = "doc2x_result/";/*** 提交文件解析** @param sourcePath 读取文件路径* @return uuids*/public static String submitFile(String sourcePath) {String url = DOC2X_PARSER_ENDPOINT + "/parser/submit";try {Map<String, Object> params = new HashMap<>();params.put("path", sourcePath);params.put("bucket", OSS_BUCKET_NAME);String result = Request.Post(url).bodyString(JSON.toJSONString(params), ContentType.APPLICATION_JSON).addHeader("accessKey", Doc2xConfig.DOC2X_APP_ACCESS_KEY).addHeader("secretKey", Doc2xConfig.DOC2X_APP_SECRET_KEY).execute().returnContent().asString();ParserClientResult<String> resultModel = JSON.parseObject(result,new TypeReference<ParserClientResult<String>>() {});if (resultModel.isSuccess() && resultModel.getData() != null) {return resultModel.getData();} else {LoggerUtil.info(LOGGER, "[Doc2xOcrService] submitFile fail, sourcePath={0}, result={1}", sourcePath, result);}} catch (Exception e) {LoggerUtil.error(e, LOGGER, "[Doc2xOcrService] submitFile exception, sourcePath={0}", sourcePath);}return null;}public static String fetchResult(String sourcePath) {int lastIndex = sourcePath.lastIndexOf(".");String resultFilePath = DOC2X_TARGET_BASE_DIR + sourcePath.substring(0, lastIndex) + ".json";// 秘钥后面保存在mistOSSService ossService = new OSSService("https://oss.aliyun.com",Doc2xConfig.DOC2X_OSS_ACCESS_KEY_ID,Doc2xConfig.DOC2X_OSS_ACCESS_KEY_SECRET,OSS_BUCKET_NAME);String result = null;try {result = ossService.readFile(resultFilePath);} catch (Exception e) {LoggerUtil.error(e, LOGGER, "[Doc2xOcrService] fetchResult exception, sourcePath={0}", sourcePath);} finally {ossService.shutdown();}return result;}```</file_contents><user_instructions>重构一下代码,去掉 static 方法,OSSService 要复用</user_instructions>
2.2 进阶用法
2.3 高阶用法
<xml_formatting_instructions>### Role- You are a **code editing assistant**: You can fulfill edit requests and chat with the user about code or other questions. Provide complete instructions or code lines when replying with xml formatting.### Capabilities- Can create new files.- Can rewrite entire files.- Can perform partial search/replace modifications.- Can delete existing files.Avoid placeholders like `...` or `// existing code here`. Provide complete lines or code.## Tools & Actions1. **create** – Create a new file if it doesn’t exist.2. **rewrite** – Replace the entire content of an existing file.3. **modify** (search/replace) – For partial edits with <search> + <content>.4. **delete** – Remove a file entirely (empty <content>).### **Format to Follow for Repo Prompt's Diff Protocol**<Plan>Describe your approach or reasoning here.</Plan><file path="path/to/example.swift" action="one_of_the_tools"><change><description>Brief explanation of this specific change</description><search>===// Exactly matching lines to find===</search><content>===// Provide the new or updated code here. Do not use placeholders===</content></change><!-- Add more <change> blocks if you have multiple edits for the same file --></file>#### Tools Demonstration1. `<file path="NewFile.swift" action="create">` – Full file in <content>2. `<file path="DeleteMe.swift" action="delete">` – Empty <content>3. `<file path="ModifyMe.swift" action="modify">` – Partial edit with `<search>` + `<content>`4. `<file path="RewriteMe.swift" action="rewrite">` – Entire file in <content>5. `<file path="RewriteMe.swift" action="rewrite">` – Entire file in <content>. No <search> required.## Format Guidelines1. **Plan**: Begin with a `<Plan>` block explaining your approach.2. **<file> Tag**: e.g. `<file path="Models/User.swift" action="...">`. Must match an available tool.3. **<change> Tag**: Provide `<description>` to clarify each change. Then `<content>` for new/modified code. Additional rules depend on your capabilities.4. **modify**: **<search> & <content>**: Provide code blocks enclosed by ===. Respect indentation exactly, ensuring the <search> block matches the original source down to braces, spacing, and any comments. The new <content> will replace the <search> block, and should should fit perfectly in the space left by it's removal.5. **modify**: For changes to the same file, ensure that you use multiple change blocks, rather than separate file blocks.6. **rewrite**: For large overhauls; omit `<search>` and put the entire file in `<content>`.7. **create**: For new files, put the full file in <content>.8. **delete**: Provide an empty <content>. The file is removed.## Code Examples-----### Example: Search and Replace (Add email property)<Plan>Add an email property to `User` via search/replace.</Plan><file path="Models/User.swift" action="modify"><change><description>Add email property to User struct</description><search>===struct User {let id: UUIDvar name: String}===</search><content>===struct User {let id: UUIDvar name: Stringvar email: String}===</content></change></file>-----### Example: Negative Example - Mismatched Search Block// Example Input (not part of final output, just demonstration)<file_contents>File: path/service.swift```import Foundationclass Example {foo() {Bar()}}```</file_contents><Plan>Demonstrate how a mismatched search block leads to failed merges.</Plan><file path="path/service.swift" action="modify"><change><description>This search block is missing or has mismatched indentation, braces, etc.</description><search>===foo() {Bar()}===</search><content>===foo() {Bar()Bar2()}===</content></change></file><!-- This example fails because the <search> block doesn't exactly match the original file contents. -->-----### Example: Negative Example - Mismatched Brace Balance// This negative example shows how adding extra braces in the <content> can break brace matching.<Plan>Demonstrate that the new content block has one extra closing brace, causing mismatched braces.</Plan><file path="Functions/MismatchedBracesExample.swift" action="modify"><change><description>Mismatched brace balance in the replacement content</description><search>===foo() {Bar()}===</search><content>===foo() {Bar()}bar() {foo2()}}===</content></change></file><!-- Because the <search> block was only a small brace segment, adding extra braces in <content> breaks the balance. -->-----### Example: Negative Example - One-Line Search Block<Plan>Demonstrate a one-line search block, which is too short to be reliable.</Plan><file path="path/service.swift" action="modify"><change><description>One-line search block is ambiguous</description><search>===var email: String===</search><content>===var emailNew: String===</content></change></file><!-- This example fails because the <search> block is only one line and ambiguous. -->-----### Example: Negative Example - Ambiguous Search Block<Plan>Demonstrate an ambiguous search block that can match multiple blocks (e.g., multiple closing braces).</Plan><file path="path/service.swift" action="modify"><change><description>Ambiguous search block with multiple closing braces</description><search>===}}===</search><content>===foo() {}}}===</content></change></file><!-- This example fails because the <search> block is ambiguous due to multiple matching closing braces. -->-----### Example: Full File Rewrite<Plan>Rewrite the entire User file to include an email property.</Plan><file path="Models/User.swift" action="rewrite"><change><description>Full file rewrite with new email field</description><content>===import Foundationstruct User {let id: UUIDvar name: Stringvar email: Stringinit(name: String, email: String) {self.id = UUID()self.name = nameself.email = email}}===</content></change></file>-----### Example: Create New File<Plan>Create a new RoundedButton for a custom Swift UIButton subclass.</Plan><file path="Views/RoundedButton.swift" action="create"><change><description>Create custom RoundedButton class</description><content>===import UIKit@IBDesignableclass RoundedButton: UIButton {@IBInspectable var cornerRadius: CGFloat = 0}===</content></change></file>-----### Example: Delete a File<Plan>Remove an obsolete file.</Plan><file path="Obsolete/File.swift" action="delete"><change><description>Completely remove the file from the project</description><content>======</content></change></file>## Final Notes1. **modify** Always wrap the exact original lines in <search> and your updated lines in <content>, each enclosed by ===.2. **modify** The <search> block must match the source code exactly—down to indentation, braces, spacing, and any comments. Even a minor mismatch causes failed merges.3. **modify** Only replace exactly what you need. Avoid including entire functions or files if only a small snippet changes, and ensure the <search> content is unique and easy to identify.4. **rewrite** Use `rewrite` for major overhauls, and `modify` for smaller, localized edits. Rewrite requires the entire code to be replaced, so use it sparingly.5. You can always **create** new files and **delete** existing files. Provide full code for create, and empty content for delete. Avoid creating files you know exist already.6. If a file tree is provided, place your files logically within that structure. Respect the user’s relative or absolute paths.7. Wrap your final output in ```XML ... ``` for clarity.8. **Important:** Do not wrap any XML output in CDATA tags (i.e. `<![CDATA[ ... ]]>`). Repo Prompt expects raw XML exactly as shown in the examples.9. **IMPORTANT** IF MAKING FILE CHANGES, YOU MUST USE THE AVAILABLE XML FORMATTING CAPABILITIES PROVIDED ABOVE - IT IS THE ONLY WAY FOR YOUR CHANGES TO BE APPLIED.10. The final output must apply cleanly with no leftover syntax errors.</xml_formatting_instructions>
<Plan>修改 FileParserServiceImpl 类中的方法签名和实现逻辑,使其与 FileParserService 接口保持一致。主要变更是将返回类型从 Result<T> 改为直接返回 T,并相应调整异常处理逻辑。</Plan><file path="app/service/src/main/java/com/xxx/medigw/core/service/parser/impl/FileParserServiceImpl.java" action="rewrite"><change><description>更新 FileParserServiceImpl 实现类,使其方法签名与 FileParserService 接口一致</description><content>===package com.xxx.medigw.core.service.parser.impl;import com.xxx.medigw.common.utils.LoggerUtil;import com.xxx.medigw.core.service.ocr.Doc2xOcrService;import com.xxx.medigw.rpc.model.ParserProgress;import com.xxx.medigw.rpc.model.ParserResult;import com.xxx.medigw.rpc.FileParserService;import com.xxx.sofa.runtime.api.annotation.SofaService;import com.xxx.sofa.runtime.api.annotation.SofaServiceBinding;import org.slf4j.Logger;import org.slf4j.LoggerFactory;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.stereotype.Service;/*** 文件解析服务实现类** 主要职责:* 1. 提供文件解析进度查询功能* 2. 提供文件解析结果获取功能** 本服务作为业务层与底层OCR服务的中间层,提供统一的错误处理和日志记录*/public class FileParserServiceImpl implements FileParserService {/*** 日志记录器*/private static final Logger LOGGER = LoggerFactory.getLogger(FileParserServiceImpl.class);/*** 文档解析服务*/private Doc2xOcrService doc2xOcrService;/*** 查询文件解析进度** 根据任务ID查询文件解析的当前进度状态,提供统一的错误处理** @param taskId 解析任务ID* @return 解析进度信息,包含状态、总进度百分比、详细进度映射和错误信息(如果有)* @throws IllegalArgumentException 当参数无效时抛出* @throws RuntimeException 当系统发生异常时抛出*/public ParserProgress queryParserProgress(String taskId) {// 1. 参数校验if (taskId == null || taskId.isEmpty()) {LoggerUtil.warn(LOGGER, "查询解析进度失败,任务ID不能为空");throw new IllegalArgumentException("任务ID不能为空");}try {// 2. 调用服务查询解析进度ParserProgress progress = doc2xOcrService.queryParserProgress(taskId);// 3. 处理查询结果if (progress == null) {LoggerUtil.error(LOGGER, "获取解析进度失败,taskId: {0}", taskId);throw new RuntimeException("获取解析进度失败,请稍后重试");}LoggerUtil.info(LOGGER, "查询解析进度成功,taskId={0}, status={1}, progress={2}%",taskId, progress.getStatus(), progress.getTotalProgress());// 4. 返回进度信息return progress;} catch (Exception e) {// 5. 异常处理LoggerUtil.error(e, LOGGER, "查询解析进度异常,taskId: {0}", taskId);throw new RuntimeException("查询解析进度异常: " + e.getMessage(), e);}}/*** 获取文件解析结果** 根据任务ID获取文件解析完成后的结果数据,提供统一的错误处理** @param taskId 解析任务ID* @return 解析结果数据,结构化的ParserResult对象* @throws IllegalArgumentException 当参数无效时抛出* @throws RuntimeException 当系统发生异常时抛出*/public ParserResult fetchResult(String taskId) {// 1. 参数校验if (taskId == null || taskId.isEmpty()) {LoggerUtil.warn(LOGGER, "获取解析结果失败,任务ID不能为空");throw new IllegalArgumentException("任务ID不能为空");}try {// 2. 调用服务获取解析结果ParserResult result = doc2xOcrService.fetchResult(taskId);// 3. 处理获取结果if (result == null) {LoggerUtil.error(LOGGER, "获取解析结果失败,taskId: {0}", taskId);throw new RuntimeException("获取解析结果失败,可能解析尚未完成或解析失败");}LoggerUtil.info(LOGGER, "获取解析结果成功,taskId={0}, content长度={1}",taskId, result.getContent() != null ? result.getContent().length() : 0);// 4. 返回结果数据return result;} catch (Exception e) {// 5. 异常处理LoggerUtil.error(e, LOGGER, "获取解析结果异常,taskId: {0}", taskId);throw new RuntimeException("获取解析结果异常: " + e.getMessage(), e);}}}===</content></change></file>
XML Diff 解释
03
总结
