我的 AI 办公技巧梳理

170 阅读21分钟

我这里的 AI 办公指的是怎么利用 AI 来帮助我们工作,让一些简单,但是工作很重复的事情交给 AI ;或者我们不是很懂,不知道怎么实现的交给 AI 。而我们只需要专注设计,专注创意。

1. 简单但是累人的事情

这类事情简单,但是可能要做的很多,就需要耗费大量时间,而且人做这类事情还可能会出错,交给 AI 以后出错率大幅度降低,同时也可以很快的完成。

1.1. 整理文案

可能我们的项目最初没有做国际化,突然我们需要国际化,在这种情况下,我们就需要整理项目中的文案;如果没有 AI ,那么我们可以采用很容易想到的两种方式:

  1. 一个文件一个文件的查看,然后把里面的文案找出来,然后整理到 Excel 中;
  2. 写一个脚本,自动读取所有的文件,然后根据匹配规则找出所有的文案。

我们公司的有一个项目,之前就是这样的,当时我是结合这两种方式完成的国际化,但是结果还是不尽人意,还是有一些漏掉的。最初我采用的是第一种方式,但是我发现很慢,而且还得看仔细,不然会看漏;于是我使用 python 写了一个脚本,先读取文件然后使用正则表达式匹配到文案,最后输出到 Excel 中,这个方案似乎很完美,但是我发现项目中的文案很多,而且表现各不相同,有些是写在标签里面的,有一些是写在 js 代码中的,有一些中间还有变量等等,我在一边执行一边完善这个脚本,最终基本上全部完成了。

如果我使用 AI 来完成这项工作,最简单的就是把文件丢给 AI 然后让它给我整理,比如下面的代码:

const Test = () => {
  const onSubmit = () => {
    console.log("你点击了提交")
    const name = "AI 办公"
    Toast.show(`你好呀: ${name}`)
  }
  return (
    <View>
      <Text>Test</Text>
      <Text>这是测试</Text>
      <Pressable onPress={() => {
        console.log("你点击了测试提示")
        Toast.show("这是测试提示)
      }}>
        <Text>测试提示</Text>
      </Pressable>
      <Pressable onPress={onSubmit}>
        <Text>提交</Text>
      </Pressable>
    </View>
  );
};
export default Test;

我编写的提示为:

帮我整理这里面的文案,然后输出json格式,分中英文,其中的 key 根据其含义帮我命名。如: {"test": "Test"}和{"test": "测试"};同时需要满足以下:

  1. 日志的文案不需要整理;
  2. 根据代码表达的含义提取出要展示给用户看的,如果涉及变量则使用 {{变量}} 的方式来整理;
  3. 我们采用的 i18n.next 来完成国际化的,按照这个来输出。

下面是 AI 输出的结果( Claude3.5 Sonnet ):

我们发现整理的结果还是可以的,接下来我们只需要一个一个的文件交给 AI 就可以完成这项工作了。在这途中我们还需要做的一件事情就是把这些文案写到代码中,这项工作也是遵从上面的原则,所以也需要我们花费很多时间来改代码。其实在上面的回答中 AI 已经自动帮我们改好了,我们只需要将代码复制出来覆盖自己的代码即可。

现在 AI 已经帮我们做了两项工作了,第一是整理文案,第二是改代码;但是国际化的过程并不是单个文件,而是很多文件,这些文件我们还是需要自己一个一个拷贝给 AI 来完成,还是很麻烦;所以我们需要编写代码,让这一切自动化。思路就是从项目的根目录开始遍历,读取其中的每一个文件,然后将文件内容发送给 AI ,然后根据 AI 的输出结果来整理文案和修改当前文件。至于这个自动化程序,我们可以采用两种方式,第一就是根据 AI 公司提供的 API 调用来完成;第二是直接使用自动化程序发送到对话框,然后根据对话框回复的内容完成接下来的操作。第二种比较麻烦,最好使用第一种方式。

1.2. 编程语言转换

有时候我们有需求将其他语言的代码转换成我们需要语言的代码,比如对于前端来说, js 转换成 ts 代码。比如:

const getVersion = async () => {
  try {
    let latestVersion;
    if (Platform.OS === 'ios') {
      const request = await getAppStoreVersion();
      if (request.code === '0') {
        latestVersion = request?.data?.results[0]?.version;
      } else {
        SimpleToast.show(request.msg || I18n.t('failed'));
      }
    } else {
      const url =
        'https://api.appcenter.ms/v0.1/apps/seeed/SenseCAP-Mate/recent_releases?owner_name=seeed&app_name=SenseCAP-Mate';
      const result = await fetch(url, {
        method: 'GET',
        headers: {
          'Content-Type': 'application/json;charset=UTF-8',
          'X-API-Token': APP_CENTER,
        },
      }).then(res => res.json());
      latestVersion = result && result[0].short_version;
    }

    const currentVersion = DeviceInfo.getVersion();
    return {currentVersion, latestVersion};
  } catch (error) {
    console.log('版本号获取--', error);
  }
  return {};
};

我输入的提示词为:

将上面代码转换成 ts 的实现

得到的结果为:

interface VersionInfo {
  currentVersion?: string;
  latestVersion?: string;
}

const getVersion = async (): Promise<VersionInfo> => {
  try {
    let latestVersion: string | undefined;

    if (Platform.OS === 'ios') {
      const request = await getAppStoreVersion();
      if (request.code === '0') {
        latestVersion = request.data?.results[0]?.version;
      } else {
        SimpleToast.show(request.msg || I18n.t('failed'));
      }
    } else {
      const url = 'https://api.appcenter.ms/v0.1/apps/seeed/SenseCAP-Mate/recent_releases?owner_name=seeed&app_name=SenseCAP-Mate';
      const result = await fetch(url, {
        method: 'GET',
        headers: {
          'Content-Type': 'application/json;charset=UTF-8',
          'X-API-Token': APP_CENTER,
        },
      }).then(res => res.json());
      latestVersion = result && result[0]?.short_version;
    }
    const currentVersion = DeviceInfo.getVersion();
    return { currentVersion, latestVersion };
  } catch (error) {
    console.log('版本号获取--', error);
  }
  return {};
};

export default getVersion;

总的来说是很 ok 的。我平时的工作中还会遇到需要将 java 转换成 kotlin ,将 oc 转换成 swift 等等需求,有了 AI 就方便很多了。如果你完全不懂目标语言,我觉得在目前的情况下是行不通的,也就是说如果你完全不懂 ts ,那么你就没办法知道其转换的结果是否正确;你需要对目标语言大致的了解。

像 ts 和 js 之间的转换还不能提现 AI 的美,因为这两者之前的转换手动也是可以做到的,而且也不是很麻烦,当然比起 AI 来还是要慢不少。如果你是从 js 转换成 java 这样的操作, AI 就非常好用了。还是上面的代码,我让其转换成 java 实现:

import android.os.AsyncTask;
import android.os.Build;
import android.util.Log;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.HashMap;
import java.util.Map;

public class VersionChecker {
    private static final String TAG = "VersionChecker";
    private static final String APP_CENTER_URL = "https://api.appcenter.ms/v0.1/apps/seeed/SenseCAP-Mate/recent_releases?owner_name=seeed&app_name=SenseCAP-Mate";
    private static final String APP_CENTER_TOKEN = "YOUR_APP_CENTER_TOKEN"; // 替换为实际的 App Center Token

    public interface VersionCallback {
        void onVersionReceived(String currentVersion, String latestVersion);
        void onError(String errorMessage);
    }

    public static void getVersion(final VersionCallback callback) {
        new AsyncTask<Void, Void, Map<String, String>>() {
            @Override
            protected Map<String, String> doInBackground(Void... voids) {
                Map<String, String> result = new HashMap<>();
                try {
                    String latestVersion = null;
                    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
                        // iOS 版本检查逻辑在 Android 上不适用,这里应该实现 Android 特定的逻辑
                        // 例如,从 Google Play 获取最新版本
                        // 这里仅作为示例,实际实现可能需要使用 Google Play Developer API
                        latestVersion = getPlayStoreVersion();
                    } else {
                        URL url = new URL(APP_CENTER_URL);
                        HttpURLConnection connection = (HttpURLConnection) url.openConnection();
                        connection.setRequestMethod("GET");
                        connection.setRequestProperty("Content-Type", "application/json;charset=UTF-8");
                        connection.setRequestProperty("X-API-Token", APP_CENTER_TOKEN);

                        BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream()));
                        StringBuilder response = new StringBuilder();
                        String line;
                        while ((line = reader.readLine()) != null) {
                            response.append(line);
                        }
                        reader.close();

                        JSONArray jsonArray = new JSONArray(response.toString());
                        if (jsonArray.length() > 0) {
                            JSONObject firstRelease = jsonArray.getJSONObject(0);
                            latestVersion = firstRelease.getString("short_version");
                        }
                    }

                    String currentVersion = getCurrentVersion();
                    result.put("currentVersion", currentVersion);
                    result.put("latestVersion", latestVersion);
                } catch (Exception e) {
                    Log.e(TAG, "Error getting version: " + e.getMessage());
                }
                return result;
            }

            @Override
            protected void onPostExecute(Map<String, String> result) {
                String currentVersion = result.get("currentVersion");
                String latestVersion = result.get("latestVersion");
                if (currentVersion != null && latestVersion != null) {
                    callback.onVersionReceived(currentVersion, latestVersion);
                } else {
                    callback.onError("Failed to retrieve version information");
                }
            }
        }.execute();
    }

    private static String getCurrentVersion() {
        return BuildConfig.VERSION_NAME;
    }

    private static String getPlayStoreVersion() {
        // 这里应该实现从 Google Play 获取最新版本的逻辑
        // 由于这需要使用 Google Play Developer API,这里只返回一个占位符
        return "1.0.0";
    }
}

如果涉及到语言之间的转换,用 AI 就对了。同样的如果你想批量的转换代码,那么就需要你编写脚本来完成。

1.3. 变量名,函数名,类名等

我们在写代码的过程中,有时候会因为一个变量的命名而绞尽脑汁,因为你希望你的命名是一目了然的,这样下次再查看代码的时候就更容易明白其含义。如果你跟我一样还英语不好,那么使用 AI 来做这个事情就非常的好。

"将测量量数据转换成渲染数据"翻译成js函数名称

这样我就得到了:

这样就不会因为想不出啥名称而闷闷不乐了。如果你对名称还有特殊的规则,那么你可以把这些规则都告诉 AI 就可以了。其实命名这个事情我们只是纠结,可能我们思考半天的命名最终也没能达到我们最初的设想,如果我们交给 AI 就不会有这样的问题了。

1.4. 给函数添加单元测试

写单元测试也是很耗时的事情,现在有 AI 我们就可以将这个事情交给 AI 了。下面我给出判断 url 是否有端口号的函数,如下:

function hasPort(url: string) {
  // 如果 url 是空的或不是字符串,返回 false
  if (!url || typeof url !== 'string') {
    return false;
  }
  try {
    // 使用 URL 构造函数解析 URL
    const parsedUrl = new URL(url);
    // 检查 port 属性是否为空
    // 注意:如果使用默认端口(如 HTTP 的 80 或 HTTPS 的 443),port 会是空字符串
    return parsedUrl.port !== '';
  } catch (error) {
    // 如果 URL 无效,捕获错误并返回 false
    return false;
  }
}

这个函数就是判断给定的 url 是否包含端口号,默认的端口号不算,比如 80 等等。我的提示词为:

帮我给这个函数生成单元测试

AI 的回复结果为:

import { hasPort } from './hasPort'; // 假设函数在 hasPort.ts 文件中

describe('hasPort function', () => {
  test('应该对带有非默认端口的 URL 返回 true', () => {
    expect(hasPort('http://example.com:8080')).toBe(true);
    expect(hasPort('https://example.com:3000')).toBe(true);
    expect(hasPort('ftp://example.com:21')).toBe(true);
  });

  test('应该对使用默认端口的 URL 返回 false', () => {
    expect(hasPort('http://example.com')).toBe(false);
    expect(hasPort('https://example.com')).toBe(false);
    expect(hasPort('http://example.com:80')).toBe(false);
    expect(hasPort('https://example.com:443')).toBe(false);
  });

  test('应该对不包含端口的 URL 返回 false', () => {
    expect(hasPort('http://example.com/path')).toBe(false);
    expect(hasPort('https://example.com/path?query=value')).toBe(false);
  });

  test('应该对无效的 URL 返回 false', () => {
    expect(hasPort('invalid-url')).toBe(false);
    expect(hasPort('http://')).toBe(false);
  });

  test('应该对空字符串返回 false', () => {
    expect(hasPort('')).toBe(false);
  });

  test('应该对非字符串输入返回 false', () => {
    expect(hasPort(null as any)).toBe(false);
    expect(hasPort(undefined as any)).toBe(false);
    expect(hasPort(123 as any)).toBe(false);
    expect(hasPort({} as any)).toBe(false);
  });

  test('应该正确处理带有用户名和密码的 URL', () => {
    expect(hasPort('http://user:pass@example.com:8080')).toBe(true);
    expect(hasPort('https://user:pass@example.com')).toBe(false);
  });

  test('应该正确处理 IPv6 地址', () => {
    expect(hasPort('http://[2001:db8::1]:8080')).toBe(true);
    expect(hasPort('http://[2001:db8::1]')).toBe(false);
  });
});

AI 编写单元测试的时候,如果你的函数名称或者有注释说明的话,那么它就会根据这些来编写单元测试,而不是你的实现,当然这些你最好都告诉 AI ,也就是需不需要根据其函数实现来。下面我把这个函数的实现弄成空的,再让其生成单元测试,由于 AI 会有上下文,所以我单开一个会话来测试。

function hasPort(url: string) { } 帮我生成单元测试

下面是 AI 帮我生成的单元测试:

import { hasPort } from './hasPort'; // 假设函数在 hasPort.ts 文件中

describe('hasPort', () => {
  test('应该对包含端口的 URL 返回 true', () => {
    expect(hasPort('http://example.com:8080')).toBe(true);
    expect(hasPort('https://localhost:3000')).toBe(true);
    expect(hasPort('ftp://192.168.1.1:21')).toBe(true);
  });

  test('应该对不包含端口的 URL 返回 false', () => {
    expect(hasPort('http://example.com')).toBe(false);
    expect(hasPort('https://www.google.com')).toBe(false);
    expect(hasPort('ftp://192.168.1.1')).toBe(false);
  });

  test('应该正确处理 IP 地址', () => {
    expect(hasPort('http://127.0.0.1:8080')).toBe(true);
    expect(hasPort('https://192.168.0.1:443')).toBe(true);
    expect(hasPort('http://10.0.0.1')).toBe(false);
  });

  test('应该正确处理带有路径和查询参数的 URL', () => {
    expect(hasPort('http://example.com:8080/path')).toBe(true);
    expect(hasPort('https://api.example.com:3000/v1/users?id=123')).toBe(true);
    expect(hasPort('http://example.com/path?param=value')).toBe(false);
  });

  test('应该处理无效的 URL', () => {
    expect(hasPort('not a url')).toBe(false);
    expect(hasPort('')).toBe(false);
  });

  test('应该正确处理 IPv6 地址', () => {
    expect(hasPort('http://[2001:db8::1]:8080')).toBe(true);
    expect(hasPort('https://[2001:db8::1]')).toBe(false);
  });
});

虽然单元测试中并不包含对默认端口号的处理,但是仅仅凭借其函数名称和参数就能生成这样的单元测试已经非常好了。如果要想对默认端口号的处理,那么你只需要给函数添加上注释就能做到。

// 判断给定 url 是否包含端口号,默认端口号除外

function hasPort(url: string) { }

帮我生成单元测试

其对应的结果为:

import { hasPort } from './urlUtils'; // 假设函数定义在 urlUtils.ts 文件中

describe('hasPort function', () => {
  test('should return false for URLs without explicit port', () => {
    expect(hasPort('http://example.com')).toBe(false);
    expect(hasPort('https://example.com')).toBe(false);
    expect(hasPort('http://example.com/path')).toBe(false);
    expect(hasPort('https://example.com/path?query=value')).toBe(false);
  });

  test('should return false for URLs with default ports', () => {
    expect(hasPort('http://example.com:80')).toBe(false);
    expect(hasPort('https://example.com:443')).toBe(false);
  });

  test('should return true for URLs with non-default ports', () => {
    expect(hasPort('http://example.com:8080')).toBe(true);
    expect(hasPort('https://example.com:8443')).toBe(true);
    expect(hasPort('http://localhost:3000')).toBe(true);
    expect(hasPort('https://api.example.com:5000/v1')).toBe(true);
  });

  test('should handle IP addresses correctly', () => {
    expect(hasPort('http://192.168.1.1')).toBe(false);
    expect(hasPort('https://192.168.1.1:443')).toBe(false);
    expect(hasPort('http://192.168.1.1:8080')).toBe(true);
  });

  test('should handle URLs with username and password', () => {
    expect(hasPort('http://user:pass@example.com')).toBe(false);
    expect(hasPort('https://user:pass@example.com:443')).toBe(false);
    expect(hasPort('http://user:pass@example.com:8080')).toBe(true);
  });

  test('should return false for invalid URLs', () => {
    expect(hasPort('not a url')).toBe(false);
    expect(hasPort('http:/example.com')).toBe(false);
    expect(hasPort('example.com:80')).toBe(false);
  });
});

这里的单元测试就已经包含对默认端口号的处理了。同时我们会发现这里输出的都是英文的,这就是 AI 不好的地方,只要你没说的基本上回答的也是随机的;所以在编写提示词的时候,一定要对你要求的都告诉 AI ,不然回答的可能就达不到自己的要求。

1.5. 纯函数实现

如果你要编写的函数是纯函数,那么交给 AI 一定是非常好的事情。至于什么是纯函数,可以参考这篇文章:什么是纯函数,纯函数在函数式编程中有什么作用?如果函数包含业务代码,要想让 AI 来完成就需要你提供足够多的上下文,这样 AI 才能做得让你满意。但是话又说过来,我们使用 AI 就是希望简单高效,如果你因此而编写了大量的数据,有点不符合初衷,当然这样其实也是有好处的,也就是这个过程你可以梳理你的逻辑。

现在拥有 AI 了,我们在编写函数的时候尽可能先写注释(特别是纯函数),这样 AI 就能帮你生成对应的代码;现在的 IDE 都能具备这样的功能,在 VSCode 中我们可以使用 MarsCode ,这个是完全免费的,是基于豆包的产品。而且现在基于此已经有了对应的 IDE 了。

同样是上面的函数,我在编辑器中写出上面的注释就能自动生成下面的代码。

1.6. 代码实现转换和代码优化

有时候我们有需求将实现转换成另一种实现,比如递归实现转换成 for 循环;还有将个别实现整合成更优雅的实现。比如我们将求指数的函数,先使用递归实现。

下面我将其转换成 while 循环的方式实现。

首先我这样跟 AI 说明。其输出结果为:

// 求给定数字的指数,比如输入 2, 3 得到结果 8 ,使用 while 循环实现
export function getExponentiation(base: number, exponent: number): number {
  let result = 1;
  while (exponent > 0) {
    result *= base;
    exponent--;
  }
  return result;
}

连注释都帮我改了,是不是非常好。在编写代码的过程中, if-else 是非常常见的,但 if-else 写多了也是很难读的,当然比起三目运算符, if-else 就更好读一些,下面我举例来优化这些实现。

// 传入一个数,如果是 1 就返回 A ,以此类推,如果是 3 就是 C,输入1-10,使用 if-else 的方式实现
export function getLetterByNumber(num: number): string {
  if (num === 1) {
    return 'A';
  } else if (num === 2) {
    return 'B';
  } else if (num === 3) {
    return 'C';
  } else if (num === 4) {
    return 'D';
  } else if (num === 5) {
    return 'E';
  } else if (num === 6) {
    return 'F';
  } else if (num === 7) {
    return 'G';
  } else if (num === 8) {
    return 'H';
  } else if (num === 9) {
    return 'I';
  } else if (num === 10) {
    return 'J';
  } else {
    return 'Unknown';
  }
}

然后我告诉 AI 使用策略模式优化代码。

下面的代码将非常的优雅。

export function getLetterByNumber(num: number): string {
  const letterMap: {[key: number]: string} = {
    1: 'A',
    2: 'B',
    3: 'C',
    4: 'D',
    5: 'E',
    6: 'F',
    7: 'G',
    8: 'H',
    9: 'I',
    10: 'J',
  };

  return letterMap[num] || 'Unknown';
}

转换代码最大的好处在于我们可以专注于思路的实现,也就是我们不关心代码的优雅,比如我们可以一直写 if-else ;因为这样很符合我们的思维;我们可以完全按照自己大脑的逻辑来实现,优化和转换交给 AI 来完成。

上面的操作我是使用 Cursor 来实现的。这个目前是收费的,只不过有免费的次数,当然这个好像支持私有化,具体我还没仔细研究过。将来我大概率要换成 MarsCode ,因为这个是国内的。

1.7. 总结

在开发的过程中,很多简单的事情,但是又不得不做,我们都可以考虑使用 AI 来简化这个过程;有时候其实并不能简化过程,但是可以减少我们的思考,减少思考也是很好的,这样我们可以将更多的精力放到其他更重要的事情上。

我这里只是抛砖引玉,更多更好玩的我们大家一块探索。也欢迎各位看官能分享你觉得最让你受益的方式方法,我们一起变得更强。

也许有人会问,将来都是 AI 来写代码了,我们是不是就被干掉了;我的想法是这个是必然的,但干掉的不是我们,而是我们的不与时俱进。当工具变化后,我们的专注点也会改变,当下可能我们专注的是根据业务写具体的代码,将来我们干的活就是根据业务思考怎么实现更好这个点上,也就是技术方案的制定上;再再将来可能就不需要我们了,我们应该做的不是写代码,而是变成创意者,发散思维,一旦有好的想法我们就可以让 AI 来实现。

2. 你有想法但是不知道怎么实现

如果你不是开发,那么你的这个想法就更加强烈,比如你想有一个工具方便你干啥,但是你不会写代码,你只能望洋兴叹。打个比方,图片压缩,图片转换这些,当前网上已经有很多了,有些需要收费,有些是免费,你可以使用网上的,但是如果你觉得把图片上传到网上不安全,那么你就可以自己写一个;可是你不会,现在有了 AI 的加持,你完全可以实现你的这个想法。其实就目前来说这些即便网上的你觉得不安全,网上也有本地部署的,也有代码直接可以用。之前我使用 AI 编写一个图片裁切的工具,分享出来让大家看看,我编写这个没有写一行代码,我只是在这个过程中不断告诉 AI ,哪些它写的不符合需求,并且告诉它应该呈现什么样子等等。体验地址:简单图片裁切

我们在开发过程中有时候想要找满足某种功能的库,如果我们通过 github 来寻找的话,我们可以按照关键词等方式来寻找,但是由于 github 上很多都是英语的,所以你得翻译成英文,而且翻译的英文不一定就是关键词。现在你有 AI 就可以很方便的找到对应的功能的库了,打个比如我想知道 react-native 闪屏页怎么实现,我就可以说:

在 react-native 中怎么实现闪屏页,有没有好用的第三方库

AI 给我提供的方法:

还有一些我就不截屏了。给我推荐的也是我们目前使用的,我去看了看也都是 star 比较多的。我在平时的开发中,现在已经使用这种方式来寻找库了。

虽然我工作范畴也是前端的一部分,但是我在 web 开发上有很多并不是很懂,我编写的日志系统就是使用 vue3 来实现的,里面大部分都是 html 的代码,有一些我不懂的情况下我就是直接问 AI 怎么实现。比如由于日志数量很多,如果直接使用 for 循环渲染每一条数据,一定会导致后面会很卡,我又不想自己去编写这个列表,于是我采用的就是问 AI ,有没有什么高性能的列表组件,结果 AI 给我推荐的是 vue-virtual-scroller ,我使用后性能好了很多。

目前我的日志系统还存在很多不友好的地方,比如使用的人需要自己填写 IP 地址,而且要保证 App 和日志系统在同一个局域网内,这些对于我明白的人来说,当然没啥问题,但是对于一个不知道的人来说就很麻烦;所以我打算将其改成自发现的,也就是只要日志系统和 App 在同一个网络,那么就能发现到,然后就弹框提示建立连接。对于这个需求我之前没有涉及过,没有接触过,我并不知道怎么做;现在我就是直接问 AI ,它提供可实现的方案,我根据其提供的方案去具体的实现。

我们有了 AI 就可以从以前的根据知识储备来实现变成根据想法来探索最佳实践。这样我们的想法就可以最大限度实现,而不是一头雾水。当然一切的前提是你得有对应的认知,也就是你完全意识不到的东西你是不会发现的。如果你连程序都不知道就谈不上实现。所以我们要尽可能的提升自己的认知,提升自己的知识广度。慢慢的我们不需要掌握代码的细节,因为细节 AI 会帮我们完成。

你会发现当你啥都不知道的时候,由于你问的太宽泛得到的答案也是很宽泛的,这个时候反而会让你觉得 AI 没用,甚至觉得对方在胡说八道。虽然我们最想要 AI 达到的要求目前还做不到,将来可能会达到。但就目前来说,我们要做的就是足够了解你要问的。也就是你要知道你问的是啥,知道你到底想要的是啥。

3. 其他杂谈

你一定不要小看 AI ,因为 AI 每天都在进步,有些东西只是你不知道,并不代表它不能,比如我们前端觉得 AI 没办法根据 UI 画界面,其实不然,现在的 AI 已经能根据 UI 图来编写界面,就目前我的体验来说,写出来的界面还不能完全满足需求,但是一些简单的界面已经能驾驭了,至少界面架子已经大差不差了。目前我还看到一些直接支持 UI 生成界面的工具了。

挡在我们前面还有 AI 没办法根据业务来写界面;其实不然,这里的困难点不是在 AI ,而是在业务由于很多都是文档或者口头上的,如果把这些都告诉 AI ,你猜会发生什么。如果我们真的需要 AI 来帮助开发,那么我们要做的就是尽量让 AI 能知道这一切;那这些在将来就不再是不可能。

我们知道 AI 的上下文是有 token 限制的,如果你输入的太多,可能 AI 只能读取一部分;同样 AI 回复也是受限的,不能一次性回复太多内容。即便输入很多是允许的,但是在理解上也是困难的,我们知道目前 AI 输出的结果我们需要手动检查一下,如果输入的太多,那么我们就不方便排查。最好的还是输入尽可能的少。那既然如此,我们在跟 AI 沟通的时候就会受到一些限制,其实话说过来,即便我们跟人沟通也是这样子的,不能跟别人说得太多,即便当时记住了,保不齐很快就会忘掉。所以我觉得跟人或 AI 沟通的时候我们要注意刻意让自己保持一些克制。假如你跟我一样是写代码的,那么以下可以参考:

  1. 编写函数的时候尽可能不要让实现太多;
  2. 单个文件的代码量尽量不要太多;
  3. 尽量让大部分逻辑抽离,不要跟业务捆得太死,这样也方便进行单元测试;

这些就是我在跟 AI 沟通的过程中总结出来的;不知道各位看官怎么看待这个事情,欢迎大家评论。