Skip to content

Latest commit

 

History

History
274 lines (203 loc) · 9.48 KB

File metadata and controls

274 lines (203 loc) · 9.48 KB

哈哈,别急,咱们用大白话把这事儿说明白!你脑子里那些酷酷的想法,其实用 API 调用无非就是“怎么提问”、“怎么接答案”、“怎么让答案连续、听话”这几件事。下面我一步步来,从最简单的到稍微复杂点的,保证你听完就能动手改。


一、先用一个最小例子跑起来

假设你已经有 DeepSeek 的 API key(就是那串 sk-xxxx),先装官方 Python 库:

pip install openai

然后最简单的调用长这样:

from openai import OpenAI

client = OpenAI(
    api_key="你的API_KEY",
    base_url="https://api.deepseek.com"
)

response = client.chat.completions.create(
    model="deepseek-chat",
    messages=[
        {"role": "user", "content": "用大白话解释一下什么是递归"}
    ]
)

print(response.choices[0].message.content)

大白话解析:

  • OpenAI(...):建立一个连接,告诉它钥匙和去哪个门找 DeepSeek。
  • client.chat.completions.create:你按下“发送”键。
  • model:你想用哪个模型,这里就是 DeepSeek 的聊天模型。
  • messages:你发给模型的整个对话历史。哪怕只有一条,也要用列表装着。
  • 最后打印出模型回你的话。

如果这个能跑通,恭喜你,已经搞定最核心的东西了。


二、怎么让模型“记住”前后文?

你脑子里可能有个想法:“我要和它多聊几句,它怎么能记住我之前说的话?”其实很简单——你把每次对话的历史都塞进 messages 里就行

messages = [
    {"role": "system", "content": "你是一个喜欢用猫咪比喻的助手"},  # 系统人设(可选)
]

while True:
    user_input = input("你: ")
    messages.append({"role": "user", "content": user_input})
    
    response = client.chat.completions.create(
        model="deepseek-chat",
        messages=messages
    )
    
    assistant_reply = response.choices[0].message.content
    print("AI:", assistant_reply)
    
    messages.append({"role": "assistant", "content": assistant_reply})

关键点:

  • messages 是一个列表,始终装着从开始到现在所有的对话。
  • 每次用户说话,追加一个 {"role": "user", ...};每次 AI 回答,追加一个 {"role": "assistant", ...}
  • 系统角色(system)放在最前面就行,只发一次,告诉模型它应该扮演什么。

你脑子里的 “想法” 很多可以用 system 实现,比如:

  • “你只回答三个字以内”
  • “你用 JSON 格式回答”
  • “你假装是苏格拉底,只用反问句”

三、让模型返回结构化内容(比如 JSON)

如果你想让 AI 返回的数据能被程序直接处理,比如提取关键词、分类、生成列表,你可以用两种方法:

1. 在 systemuser 提示里硬要求

messages = [
    {"role": "system", "content": "你只返回 JSON 格式,不要任何解释。例如:{\"result\": \"...\"}"},
    {"role": "user", "content": "把下面的句子翻译成英文:‘今天天气真好’"}
]

但这个方法偶尔会不听话,会在 JSON 外面多几句废话。

2. 使用 response_format 参数(如果 DeepSeek 支持,目前很多模型支持 JSON 模式)

response = client.chat.completions.create(
    model="deepseek-chat",
    messages=[...],
    response_format={"type": "json_object"}
)

这样模型就一定会输出合法的 JSON。你再 import json 解析它。


四、流式输出(打字机效果)

你可能想让答案一个字一个字蹦出来,像 ChatGPT 网页那样。用 stream=True

stream = client.chat.completions.create(
    model="deepseek-chat",
    messages=[{"role": "user", "content": "讲个笑话"}],
    stream=True
)

for chunk in stream:
    if chunk.choices[0].delta.content:
        print(chunk.choices[0].delta.content, end="", flush=True)

注意: 流式模式下返回的对象是 delta 而不是 message,所以用 delta.content 取文本,而且可能为 None(比如第一个块可能没有内容),所以要做判断。


五、控制模型“脑洞”:temperaturetop_p

你肯定有这种感觉:有时候想让 AI 自由发挥创意,有时候又想让它完全按事实说话。这两个参数帮你控制:

  • temperature:0~2 之间,值越小越保守、越确定;值越大越随机、越有“创意”。做事实问答用 0.1 左右,写诗可以用 0.8。
  • top_p:另一种控制随机性的方法,一般和 temperature 二选一调整,不用同时改。

示例:

response = client.chat.completions.create(
    model="deepseek-chat",
    messages=[...],
    temperature=0.2
)

六、函数调用(让 AI 能“动手”)

这是实现复杂想法的利器。比如你想让 AI 帮你查天气、计算数学表达式,但它自己不会,你可以告诉它:“如果你需要查天气,就告诉我一个函数调用的格式,我替你执行再把结果给你。”

流程:

  1. 你定义一些工具(函数),描述名字、参数。
  2. 把工具列表传给 API。
  3. 如果模型觉得需要调用工具,它不会直接回答,而是返回一个 tool_calls 对象,里面有函数名和参数。
  4. 你拿到参数,在你的代码里执行对应的函数,得到结果。
  5. 把结果以 tool 角色添加到消息历史,再让模型继续生成最终回答。

举个例子(伪代码):

tools = [
    {
        "type": "function",
        "function": {
            "name": "get_weather",
            "description": "获取指定城市的天气",
            "parameters": {
                "type": "object",
                "properties": {
                    "city": {"type": "string", "description": "城市名"}
                },
                "required": ["city"]
            }
        }
    }
]

messages = [{"role": "user", "content": "北京今天天气怎么样?"}]

response = client.chat.completions.create(
    model="deepseek-chat",
    messages=messages,
    tools=tools,
    tool_choice="auto"   # 让模型自己决定要不要调用工具
)

# 检查是否要调用工具
msg = response.choices[0].message
if msg.tool_calls:
    tool_call = msg.tool_calls[0]
    function_name = tool_call.function.name
    arguments = json.loads(tool_call.function.arguments)  # 得到 {"city": "北京"}
    
    # 你执行自己的函数
    if function_name == "get_weather":
        weather_result = "晴天,25摄氏度"  # 这里换成你真实的API调用
    
    # 把函数执行结果发回去
    messages.append(msg)  # 原始模型消息(包含tool_calls)
    messages.append({
        "role": "tool",
        "tool_call_id": tool_call.id,
        "content": weather_result
    })
    
    # 再请求模型,它会基于结果生成自然语言回答
    final_response = client.chat.completions.create(
        model="deepseek-chat",
        messages=messages
    )
    print(final_response.choices[0].message.content)

这样模型就能在你的程序里“动手”了。你所有的想法比如“让AI帮我搜资料”、“操作数据库”等都可以通过这个模式实现。


七、你提到的“很多想法实现不了”可能踩的坑

  1. 忘记加 messages 历史 → 模型像个金鱼,转眼就忘。
  2. system 提示没用对 → 把要求放在第一条 system 消息里,不要放在 user 里,模型会更听话。
  3. 输出格式不稳定 → 用 response_format 或函数调用强制结构化。
  4. 一次对话太长 → 模型有上下文长度限制(比如 64k token),如果历史太长,可以定期删除前面的消息,或者只保留最近 N 轮。
  5. API 返回错误 → 总要用 try/except 包住请求,处理网络超时、额度用完等情况。

八、最后给你一个“万能模板”

你只要复制这个模板,改改里面的 system_prompt 和你的逻辑,几乎能干所有常见的事:

from openai import OpenAI
import json

client = OpenAI(api_key="你的KEY", base_url="https://api.deepseek.com")

def chat_with_ai(user_message, history=[]):
    system_prompt = "你是一个有用的助手,回答简洁,使用中文。"  # 改这里实现你的想法
    
    messages = [{"role": "system", "content": system_prompt}]
    messages.extend(history)
    messages.append({"role": "user", "content": user_message})
    
    try:
        response = client.chat.completions.create(
            model="deepseek-chat",
            messages=messages,
            temperature=0.5,
        )
    except Exception as e:
        return f"出错了:{e}", history
    
    reply = response.choices[0].message.content
    # 更新历史
    history.append({"role": "user", "content": user_message})
    history.append({"role": "assistant", "content": reply})
    
    return reply, history

# 使用
history = []
while True:
    user_input = input("你: ")
    reply, history = chat_with_ai(user_input, history)
    print("AI:", reply)

你脑子里那些“想法” 无非就是改 system_prompt,或者增加 tools,或者解析返回的内容再加工。你先拿这个跑,有问题再往里面加零件。


小结:
先把最简调用跑通,然后理解 messages 是记忆,system 是人设,tools 是手,temperature 是性格,stream 是说话方式。多试试,代码写两遍就熟悉了。有任何具体场景实现不了,可以继续问我,我们一步步拆解!