吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 2112|回复: 16
收起左侧

[Python 原创] 解决 AI 算不准,其实很简单,加部计算器

  [复制链接]
pyjiujiu 发表于 2025-1-8 21:00
前言:
这篇是个demo,目的是,让各位朋友 ,稍微感受下当前 AI 真正的发展,现在25年1月,网上争论的都是不了解的小伙伴居多
比如,纠结 AI 算不准,真没必要,人脑也是算不准,古人云,君子性非异,善假于物也。

---分割线---
装计算器,其实很简单,也就是 加个 function call,
下面是个人  基于gemini 写的,,其他模型可能要自己查询相应的API文档

为什么用 gemini?
因为这家代码,还是能有点前瞻性的,甚至有种黑科技的感觉

---分割线---
要安装的库:pip install google-genai

[Python] 纯文本查看 复制代码
001
002
003
004
005
006
007
008
009
010
011
012
013
014
015
016
017
018
019
020
021
022
023
024
025
026
027
028
029
030
031
032
033
034
035
036
037
038
039
040
041
042
043
044
045
046
047
048
049
050
051
052
053
054
055
056
057
058
059
060
061
062
063
064
065
066
067
068
069
070
071
072
073
074
075
076
077
078
079
080
081
082
083
084
085
086
087
088
089
090
091
092
093
094
095
096
097
098
099
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
from typing import Callable, Dict, List, Union, Any
import math
import dataclasses
from functools import wraps
 
from google import genai
from google.genai import types
 
API_KEY = 'xxxxxxxxxx' #需要自己的 API key,也可以写入系统的环境变量
client = genai.Client(api_key=API_KEY)
MAX_COUNT = 4
     
@dataclasses.dataclass
class Count_f_call:
    """in case of looping forever"""
    count:int = 0
    need_terminate:bool = False
func_count = Count_f_call()
 
def add_count(func):
    @wraps(func)
    def wrapper(*args,**kwargs):
        func_count.count += 1
        if func_count.count > MAX_COUNT: func_count.need_terminate = True
        return func(*args,**kwargs)
    return wrapper
 
def zero_count(func):
    def wrapper(*args,**kwargs):
        func_count.count = 0
        func_count.need_terminate = False
        func(*args,**kwargs)
    return wrapper
 
def tokenize(s: str) -> list[str]:
    """Convert a string into a list of tokens.
    e.g.tokenize('(+ 18 45)') --> ['(', '+', '18', '45', ')']
    """
    return s.replace('(', ' ( ').replace(')', ' ) ').split()
 
def parse(expression: str) -> list[str]:
    "Read a expression from a string."
    return tokenize(expression)
@add_count
def calculator(expression: str) -> Union[str, int, float]:
    """
    A calculator for performing basic arithmetic calculations.
    Args:
        expression: A string representing the expression to evaluate using prefix notation, with outermost '()'.
            Supported operations: "+", "-", "*", "/", "^", "sqrt", "abs","sin","cos", "tan", "log", "exp", "round"
            The delimiter: "(",")"
            e.g. '(+ 1 2)' or '(* (+ 1 2) 3)' or '(sqrt (+ 1 2))'
    Returns:
        The result of the calculation, or an error message string.
    """
    if func_count.need_terminate:
        return "Warning: exceed the max function call times in a single LLM call"
    available_operations: List[str] = ["+", "-", "*", "/", "^", "sqrt", "abs", "sin", "cos", "tan", "log", "exp", "round"]
    print(f"\r函数调用:{func_count.count}  算式: {expression}",end='',flush=True)
    try:
        tokens = parse(expression)
        return _evaluate_expression(tokens, available_operations)
    except Exception as e:
         return f"Error: An unexpected error occurred: {str(e)}"
 
def _evaluate_expression(tokens: list[str], available_operations: List[str]) -> Union[str, int, float]:
    """
    Recursively evaluates a list of tokens representing an expression.
    Args:
        tokens: A list of tokens representing the expression.
        available_operations: List of supported operations.
    Returns:
        The result of the calculation, or an error message string.
    """
    if not tokens:
        return "Error: Empty expression."
    if tokens[0] == '(':
        tokens.pop(0
        if not tokens:
            return "Error: Unbalanced parenthesis."
        operation = tokens.pop(0
        if operation not in available_operations:
             return f"Error: Unsupported operation: {operation}. Available operations are: {', '.join(available_operations)}"
        arguments = []
        while tokens and tokens[0] != ')':
            arg = _evaluate_expression(tokens, available_operations) 
            if isinstance(arg, str) and arg.startswith("Error:"):
                return arg
            arguments.append(arg)
        if not tokens:
            return "Error: Unbalanced parenthesis."
        tokens.pop(0)
        return _apply_operation(operation, arguments)
    try:
        return float(tokens.pop(0))
    except (ValueError, IndexError):
        return "Error: Invalid number or unexpected token."
 
def _apply_operation(operation: str, arguments: List[Union[int, float]]) -> Union[str, int, float]:
    """Applies the specified operation to the arguments."""
    match operation:
        case "+":
            return sum(arguments)
        case "-":
            if len(arguments) != 2:
                return "Error: Subtraction requires exactly 2 arguments."
            return arguments[0] - arguments[1]
        case "*":
            result = 1
            for arg in arguments:
                result *= arg
            return result
        case "/":
            if len(arguments) != 2:
                return "Error: Division requires exactly 2 arguments."
            if arguments[1] == 0:
                return "Error: Division by zero."
            return arguments[0] / arguments[1]
        case "^":
            if len(arguments) != 2:
                return "Error: Power operation requires exactly 2 arguments."
            return arguments[0] ** arguments[1]
        case "sqrt":
            if len(arguments) != 1:
                return "Error: Square root requires exactly 1 argument."
            if arguments[0] < 0:
                return "Error: Cannot take square root of negative number."
            return math.sqrt(arguments[0])
        case "abs":
            if len(arguments) != 1:
                return "Error: Absolute value requires exactly 1 argument."
            return abs(arguments[0])
        case "sin" | "cos" | "tan":
            if len(arguments) != 1:
                return f"Error: {operation} requires exactly 1 argument."
            if operation == "sin":
                return math.sin(arguments[0])
            elif operation == "cos":
                return math.cos(arguments[0])
            else:
                return math.tan(arguments[0])
        case "log":
            if len(arguments) != 1:
                return "Error: Logarithm requires exactly 1 argument."
            if arguments[0] <= 0:
                return "Error: Cannot take logarithm of non-positive number."
            return math.log(arguments[0])
        case "exp":
            if len(arguments) != 1:
                return "Error: Exponential requires exactly 1 argument."
            return math.exp(arguments[0])
        case "round":
            if len(arguments) == 1:
                return round(arguments[0])
            elif len(arguments) == 2:
                return round(arguments[0], arguments[1])
            else:
                return "Error: Rounding requires 1 or 2 arguments."
        case _:
            return "Error: Invalid operation."
 
@zero_count
def llm_call(content_text):
    response = client.models.generate_content(
        model='gemini-2.0-flash-exp',
        contents=content_text,
        config=types.GenerateContentConfig(
            system_instruction='you are helpful assistant, when encounter function call task,in addition to completing task,also keep the final raw json sent to funcition ',
            temperature= 0.7,
            tools=[calculator],
        ),
        )
    print('-' * 40)
    print(response.text)
if __name__ =="__main__":
    import os
    os.environ['http_proxy'] = 'http://127.0.0.1:8000'
    os.environ['https_proxy'] = 'http://127.0.0.1:8000'
    while True:
        content_text = input("请输入问题:").strip()
        llm_call(content_text)
        input("")



---分割线---
稍微展示下 测试

test_interface.png


--说明
其实个人用的场景也不多,所以也没怎么测试,大概记录几点

#首先如果调用 gemini ,网络问题要自己解决(可以转成 本土大模型的 function call 版本)

1  小模型对算式输出会有问题,gemini-2.0-flash-exp 就没遇到错误 (但存在 分解成小计算,调用过多的问题)
2  如果不设置 system prompt ,让LLM 必须执行计算器,对于简单的(如根号2 +1),是不会调用的 (这个 deepseek 是有必须选项,gemini 没找到)
3 代码的问题,要求Python 3.10+ ,因为 match case 的写法 (个人很喜欢 match 的写法)(大家可以自行修改 去兼容老版本)。

4 受人鱼 不如授人以渔,这篇代码,主要参考了书籍 fluent python》的解析 lisp 的部分,还有 Antropic (Claude的公司) 的官方仓库,这两个都是好东西,推荐大家多关注。


代码完全原创,本人不介意版权可以随便修改,以及分享给自己的好朋友,(不要纠结 copyright )


#最后,最近更多是在研究 AI prompt,本篇是之前做的,希望对大家有所启示,其实 AI 真的很强的 也很好用的工具,不用太在意一般的观点,很多功能本身还在探索当中,要说的话,历史上是没有任何参考的,我们才是第一代。

免费评分

参与人数 7吾爱币 +11 热心值 +6 收起 理由
苏紫方璇 + 7 + 1 欢迎分析讨论交流,吾爱破解论坛有你更精彩!
bx_liu + 1 感谢发布原创作品,吾爱破解论坛因你更精彩!
wyxa + 1 + 1 感谢发布原创作品,吾爱破解论坛因你更精彩!
mazhi1455 + 1 + 1 热心回复!
Hameel + 1 谢谢@Thanks!
czz404 + 1 + 1 我很赞同!
myqqq + 1 感谢发布原创作品,吾爱破解论坛因你更精彩!

查看全部评分

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

waningmoon 发表于 2025-1-9 11:21
对的,其他方面都还挺好,但数学问题真的一算一个不吱声,给人的感觉就是别管我算得对不对,我就问你快不快
HG2022 发表于 2025-1-9 01:15
有价值,有思想的好贴!“要说的话,历史上是没有任何参考的,我们才是第一代。”,非常赞同!
crystalZ 发表于 2025-1-8 22:21
yunyanyishi 发表于 2025-1-9 18:10
君子性非异,善假于物也。善于利用工具,提高效率,这才是人的最大优势
一场荒唐半生梦 发表于 2025-1-8 22:39
要是打包个成品就更好了
MCQSJ 发表于 2025-1-8 22:41
很强,正好在学习function call
bbk74 发表于 2025-1-9 06:54
现在问题是算的太准了。到处都是大树去杀熟啊。
kenkenss 发表于 2025-1-9 07:42
不敢相信AI竟然算不准
yxf515321 发表于 2025-1-9 07:47
AI的数学推理能力目前公认还是欠缺的,谢谢楼主分享
wjhere 发表于 2025-1-9 08:33
小白看不懂,期待成品
iawyxkdn8 发表于 2025-1-9 09:15
任何事物都不可能是完美的,AI也不例外!
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

返回列表

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - LCG - LSG ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2025-5-20 02:44

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表