8 月 31 日,以百度“文心一言”为代表的大模型产品首批通过《生成式人工智能服务管理暂行办法》备案,将通过Web、APP、API等方式,为全社会提供多种生成式AI服务。
因为文心一言是基于百度深度学习平台,可以自然地处理中文,提供中文编程环境,具有强大的自适应学习功能,能够自动生成符合语法规则的代码,辅助开发人员编程,所以自今年3月开启邀测就受到广大开发人员的关注。如今面向全社会开放无疑给开发人员提升工作效率提供了更多的可能性。
除了文心一言这样的大模型外,在代码生成垂直领域,个人还关注到一款叫做FuncGPT(慧函数)的产品。今天就来测试一下,一个背靠大厂光环;一个名不见经传,宣称专注AI生成Java函数,二者是否能够真的帮广大“码农”解燃眉之急。
我以编程中常常需要对浮点数进行精确的运算时会用到BigDecimal为例,分别在两个产品界面输入“写一个Java函数,实现bigDecimal表达式计算”。
文心一言生成的代码示例: 官网地址:https://yiyan.baidu.com
import java.math.BigDecimal;
import java.math.MathContext;
public class BigDecimalCalculator {
public static BigDecimal calculateExpression(String expression) throws Exception {
// 将字符串表达式解析为BigDecimal对象数组
BigDecimal[] operands = new BigDecimal[expression.split("\ ").length];
int index = 0;
for (String operand : expression.split("\ ")) {
operands[index] = new BigDecimal(operand.trim());
index ;
}
// 递归计算表达式
return calculateExpressionRecursive(operands, index);
}
private static BigDecimal calculateExpressionRecursive(BigDecimal[] operands, int index) throws Exception {
if (index == 0) {
return operands[0];
} else {
BigDecimal currentOperand = operands[index - 1];
BigDecimal subExpressionValue = calculateExpressionRecursive(operands, index - 1);
return currentOperand.add(subExpressionValue);
}
}
public static void main(String[] args) throws Exception {
String expression = "3.1415926 2.7182818-1.5707963";
BigDecimal result = calculateExpression(expression);
System.out.println(result.toString()); // 输出结果为:4.279685799999999
}
}
FuncGPT(慧函数)生成的代码示例:
下载地址:https://suo.im/a2pXi
// 类名:BigDecimalCalculator
// 函数名:calculateExpression
// 函数功能:使用BigDecimal计算表达式的结果
// POM依赖包:
// <dependency>
// <groupId>org.apache.commons</groupId>
// <artifactId>commons-lang3</artifactId>
// <version>3.12.0</version>
// </dependency>
import org.apache.commons.lang3.StringUtils;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.Stack;
public class BigDecimalCalculator {
/**
* 使用BigDecimal计算表达式的结果
* @param expression 要计算的表达式
* @return 计算结果
*/
public static BigDecimal calculateExpression(String expression) {
if (StringUtils.isBlank(expression)) {
throw new IllegalArgumentException("Expression cannot be blank");
}
Stack<BigDecimal> numberStack = new Stack<>();
Stack<Character> operatorStack = new Stack<>();
for (int i = 0; i < expression.length(); i ) {
char ch = expression.charAt(i);
if (Character.isDigit(ch)) {
StringBuilder sb = new StringBuilder();
while (i < expression.length() && (Character.isDigit(expression.charAt(i)) || expression.charAt(i) == '.')) {
sb.append(expression.charAt(i));
i ;
}
i--;
BigDecimal number = new BigDecimal(sb.toString());
numberStack.push(number);
} else if (ch == '(') {
operatorStack.push(ch);
} else if (ch == ')') {
while (!operatorStack.isEmpty() && operatorStack.peek() != '(') {
BigDecimal result = performOperation(numberStack, operatorStack);
numberStack.push(result);
}
if (!operatorStack.isEmpty() && operatorStack.peek() == '(') {
operatorStack.pop();
}
} else if (isOperator(ch)) {
while (!operatorStack.isEmpty() && hasHigherPrecedence(ch, operatorStack.peek())) {
BigDecimal result = performOperation(numberStack, operatorStack);
numberStack.push(result);
}
operatorStack.push(ch);
}
}
while (!operatorStack.isEmpty()) {
BigDecimal result = performOperation(numberStack, operatorStack);
numberStack.push(result);
}
return numberStack.pop();
}
private static boolean isOperator(char ch) {
return ch == ' ' || ch == '-' || ch == '*' || ch == '/';
}
private static boolean hasHigherPrecedence(char op1, char op2) {
if ((op1 == '*' || op1 == '/') && (op2 == ' ' || op2 == '-')) {
return true;
}
return false;
}
private static BigDecimal performOperation(Stack<BigDecimal> numberStack, Stack<Character> operatorStack) {
BigDecimal num2 = numberStack.pop();
BigDecimal num1 = numberStack.pop();
char operator = operatorStack.pop();
BigDecimal result;
switch (operator) {
case ' ':
result = num1.add(num2);
break;
case '-':
result = num1.subtract(num2);
break;
case '*':
result = num1.multiply(num2);
break;
case '/':
result = num1.divide(num2, 2, RoundingMode.HALF_UP);
break;
default:
throw new IllegalArgumentException("Invalid operator");
}
return result;
}
}
// 函数示例
// 使用BigDecimal计算表达式的结果示例
// 入参:expression,要计算的表达式
// 出参:result,计算结果
// 调用示例:
// String expression = "2.5 3 * (4 - 1)";
// BigDecimal result = BigDecimalCalculator.calculateExpression(expression);
// System.out.println(result);
// 输出结果:例如,计算表达式"2.5 3 * (4 - 1)"的结果为:11.5
// 则输出结果为:11.5
对二者从代码的可扩展性、健壮性等方面进行对比分析:
一、可扩展性
文心一言使用了递归方法进行表达式的计算,这种方法可以处理包含任意数量和类型的
操作数和运算符的表达式,可以方便地扩展到处理更复杂的表达。
FuncGPT使用栈的数据结构来处理表达式中的操作符和数字,通过读取每一个字符,并
根据情况进行相应的处理,灵活度及可扩展性较好。
二、健壮性
FuncGPT利用了Apache Commons Lang库中的StringUtils工具类判断表达式是否为空或空格,相较文心一言,代码的健壮性更好;
三、运算误差
文心一言和FuncGPT都使用了BigDecimal类进行浮点数的运算,这样可以避免由于浮
点数精度限制导致的运算误差。因此,在运算误差方面,两者表现相当。。
综上所述,个人基于今天的测试对比, FuncGPT(慧函数)在可扩展性和健壮性方面表现较好,但是在运算误差方面和文心一言相当。在实际应用中,开发人员可以根据具体的需求和情况来选择适合的实现方式。
随着人工智能技术的不断进步和发展,相信文心一言和FuncGPT(慧函数)将会在Java编程方面有更加出色的表现,为开发人员的生产和生活带来更多的便利和价值。