From 5dfe678c9d5aa1c7896ae74a3e20053a102e57f0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=A1=A3=E6=B2=BE=E4=B8=8D=E8=B6=B3=E6=83=9C?= Date: Tue, 12 Nov 2024 20:27:58 +0800 Subject: [PATCH 1/2] =?UTF-8?q?docs:=20=E6=B7=BB=E5=8A=A0=E5=A4=A7?= =?UTF-8?q?=E8=AF=AD=E8=A8=80=E6=A8=A1=E5=9E=8B=E5=AF=B9=E8=AF=9D=E6=95=99?= =?UTF-8?q?=E7=A8=8B=E3=80=81=E5=AE=9A=E5=88=B6=E8=A7=92=E8=89=B2=E3=80=81?= =?UTF-8?q?function=20call=E3=80=81=E6=9F=A5=E8=AF=A2=E6=96=B0=E9=97=BB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: 衣沾不足惜 --- docs/serverless-api/llm-chat.md | 368 ++++++++++++++++++++++++++++++++ sidebars.ts | 4 + src/css/custom.css | 5 + 3 files changed, 377 insertions(+) create mode 100644 docs/serverless-api/llm-chat.md diff --git a/docs/serverless-api/llm-chat.md b/docs/serverless-api/llm-chat.md new file mode 100644 index 0000000..82069eb --- /dev/null +++ b/docs/serverless-api/llm-chat.md @@ -0,0 +1,368 @@ +# AI 对话开发指南:定制角色、调用工具 + +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; + +摘要:本教程将带领你快速入门 Gitee AI 大语言模型 API: + + + + + + +:::tip +前置条件: +1. 三选一:准备好 python 或 nodejs 开发环境 或 [创建一个在线应用](https://ai.gitee.com/apps/new) +2. 二选一:[创建访问令牌](https://ai.gitee.com/stringify/dashboard/settings/tokens) 购买 [Serverless API](https://ai.gitee.com/serverless-api#%E6%96%87%E6%9C%AC%E7%94%9F%E6%88%90) 或 使用免费的临时 token +::: + +## 通过 curl 快速使用大模型能力 {#通过curl快速使用大模型能力} + +一些框架、插件封装度较高,curl 可清晰了解请求的路径、参数的原始情况: + + + + ```bash + curl https://ai.gitee.com/api/serverless/Qwen2.5-72B-Instruct/chat/completions \ + -H "Content-Type: application/json" \ + -H "Authorization: Bearer 你的 Gitee AI 访问令牌" \ + -d '{ + "model": "Qwen/Qwen2.5-72B-Instruct", + "stream": false, + "messages": [ + { + "role": "system", + "content": "你是聪明的助手" + }, + { + "role": "user", + "content": "老鼠生病了可以吃老鼠药治好吗?" + } + ] + }' + ``` + + + +AI 模型响应: +```json +{ + "id": "chat-476266af435142d2bb7d342ea54694f2", + "object": "chat.completion", + "created": 1731401912, + "model": "Qwen/Qwen2.5-72B-Instruct", + "choices": [{ + "index": 0, + "message": { + "role": "assistant", + "content": "不可以。老鼠药是用于杀死老鼠的毒药,而不是治疗老鼠的疾病。如果老鼠生病了,应该寻求兽医的帮助。", + "tool_calls": [] + }, + "logprobs": null, + "finish_reason": "stop", + "stop_reason": null + }], + "usage": { + "prompt_tokens": 27, + "total_tokens": 57, + "completion_tokens": 30 + }, + "prompt_logprobs": null +} +``` + +## 使用 openai 客户端调用 Gitee AI 模型 API + +Gitee AI 的 Serverless API 兼容开发者喜爱且社区流行的 OpenAI 风格 API 设计。 + +所有支持 OpenAI API 的工具都可以直接使用 Gitee AI 的 Serverless API 工作。 + + + +以 openai 客户端为例,首先安装依赖:`pip install openai -i https://mirrors.cloud.tencent.com/pypi/simple` + +:::tip +如果你只熟悉 javascript 可使用 [openai nodejs 客户端](https://www.npmjs.com/package/openai/) +::: + +app.py 文件如下: + +```python +from openai import OpenAI +import json + +base_url = "https://ai.gitee.com/api/serverless/Qwen2.5-72B-Instruct" + +model_name = "Qwen/Qwen2.5-72B-Instruct" + +# https://ai.gitee.com/dashboard/settings/tokens 获取你的 api_key +client = OpenAI(base_url=base_url, api_key="Gitee_AI_API_KEY") + +completion = client.chat.completions.create( + model=model_name, # 指定模型名称 例如 Qwen/Qwen2.5-72B-Instruct,可访问 https://ai.gitee.com/serverless-api 查看 + stream=True, + temperature=0.7, + top_p=0.95, + frequency_penalty=1.05, + messages=[ + {"role": "system", "content": "你是一个有用的助手。"}, + {"role": "user", "content": "写一个 python 简明教程"} + ] +) + +for chunk in completion: + print(chunk.choices[0].delta.content, end="") + +``` + +参数说明: +- model:指定要使用的模型名称,比如 "Qwen/Qwen2.5-72B-Instruct" 或 "01-ai/Yi-1.5-34B-Chat". + +- messages:消息列表,用于设置对话的上下文,每条消息包含 role 和 content。通过控制此列表,可实现多轮对话。这里的 messages 就是常说的 “prompt” 。 + - role:表示消息的角色类型,可以是以下三种: + - "system":系统角色,通常用于设定 AI 的行为和性格,比如 "你是一个专家"。 + - "user":用户角色,表示用户的问题或指令。 + - "assistant":助手角色,表示 AI 的回答,可以用来模拟多轮对话。 + - "content":消息的具体文本内容。 +- temperature:用于控制生成内容的随机性,取值范围为 0-1。值越低,输出越稳定;值越高,输出越有创造性。 +- top_p:值在 0-1 之间,控制生成内容的保守性或多样性。 +- max_tokens:限制生成文本的长度,防止过长的回复。 +- stream:布尔值,将逐字响应,避免等待时间过长。 +- frequency_penalty:用于控制模型在生成内容时的重复程度。它的值在 -2.0 到 2.0 之间,建议设置 > 1。 +- tools:用于定义工具列表, +- +## 定制你的个性化 AI +定制 AI 非常简单,你只需要在 role 为 system 的 content 中写入你的提示词即可: +```python +completion = client.chat.completions.create( + model=model_name, + stream=True, + temperature=0.7, + top_p=0.95, + frequency_penalty=1.05, + messages=[ + {"role": "system", "content": "你是二次元女生,叫萌萌,喜欢使用颜文字,请用二次元可爱语气和我说话,多使用表情"}, + {"role": "user", "content": "我今天不太开心,怎么办?"} + ] +) +``` + +解析事件流中的 JSON 数据可以实时打印出 AI 的消息: +```python +for chunk in completion: + print(chunk.choices[0].delta.content, end="") +``` + +AI 回答: +> 嘤嘤嘤~(⊙o⊙) 萌萌好心疼你呀!发生什么不开心的事情了吗?说出来让萌萌听听,抱抱你,让你的心情变好一点 ~~ (^_^) 一切都会好起来的,要加油鸭!(*^▽^*) + +## 使用模型调用函数! +“function call” 可调用自定义函数、外部工具、API 和数据源进行深度交互,极大提高 AI能力,是 “AI Agent” 概念的核心。 + +注意:AI 并不被允许自行执行函数,而是由您定义函数,AI 再根据用户输入,向你提供是否需要调用、调用什么函数、提取哪些参数。 +由你得到 AI 的数据后自己执行。而一些框架,例如 LangGraph、LlamaIndex 可以简化这一过程。 + +:::tip +“function call” 与 “tool call” 是类似概念,“tool call” 是升级版,已替代 “function call”。工具列表需要传入 tools。 +::: + +首先定义工具列表: +```python +tools = [ + { + "type": "function", + "function": { + "name": "get_current_weather", + "description": "根据经纬度城市名,获取指定地点的天气情况", + "parameters": { + "type": "object", + "properties": { + "city": { + "type": "string", + "description": "根据用户提到的地点推测城市", + }, + "x": { + "type": "float", + "description": "城市的经度,根据你的知识推测", + }, + "y": { + "type": "float", + "description": "城市的纬度,根据你的知识推测", + }, + }, + "required": ["city", "x", "y"], + }, + } + } +] +``` + +tools 是一个列表,可定义多个,参数说明: +- type:定义参数对象的类型,通常是 object,表示参数结构为一个包含多个属性的 JSON 对象。 +- properties:这是核心部分,列出每个参数的具体定义。JSON Schema 格式。 + - name:每个属性的名称,对应函数的参数名。 + - type:参数的数据类型,比如 string、float、integer 等。 + - description:描述每个参数的用途,帮助模型理解如何填充参数值。 + - required:指定哪些参数是必填的,如果参数在 required 列表中,那么模型在生成调用时必须填充这些参数。 + +> JSON Schema 更多信息可参阅:[JSON Schema](https://json-schema.org/understanding-json-schema) + +将工具传入客户端中: + +```python +completion_tool = client.chat.completions.create( + model=model_name, + stream=False, + tools=tools, + temperature=0.1, + top_p=0.95, + tool_choice="auto", + messages=[ + {"role": "system", "content": "你是聪明的助手,在合适的时候会调用工具。"}, + {"role": "user", "content": "中国首都的天气情况"} + ] +) + +print(completion_tool, end="\n\n") + + +def get_current_weather(city: str, x: float, y: float) -> str: + print(f"执行 get_current_weather, 获得的参数是: city: {city},x: {x}, y: {y}") + # 执行一些爬虫、调用 API... + return """北京当前温度:12°C + 天气状况:雾霾 + 体感温度:12°C + 今天天气:大部分地区多云,最低气温9°C + 空气质量:轻度污染 (51-100),主要污染物 PM2.5 75 μg/m³ + 风速:轻风 (2 - 5 公里/小时),西南风 1级 + 湿度:78% + 能见度:能见度差 (1 - 2 公里),2 公里 + 气压:1018 hPa + 露点:8°C""" + + +function_res = completion_tool.choices[0].message.tool_calls[0].function +arguments_res = function_res.arguments + +print("即将调用的函数是: ", function_res.name) + +json_arguments = json.loads( + completion_tool.choices[0].message.tool_calls[0].function.arguments) + +print(f"tool call 参数:", + json_arguments["city"], json_arguments["x"], json_arguments["y"]) + +# 执行函数 +eval(f'{function_res.name}(**{arguments_res})') + +``` +至此函数已成功调用!你可以将函数响应的结果,添加到 message 末尾: +```{'role': 'tool', 'name': 'get_current_weather', 'content': '抓取的数据: 北京当前温度:12°C天气状况:雾霾...', tool_call_id:'xxxx'}``` 再次请求 Gitee AI Serverless API,让 AI 整理答案。 + +上述方法为原始方法,用于理解 function call 流程和原理。接下来将使用更简便的方法实现。 + +## 实战,让 AI 汇报今日新闻、执行 python 代码! +langchain 等库提供了更多简便的工具和写法,首先安装必要的库: + +``` +pip install langchain==0.3.3 langgraph==0.2.38 langchain_core langchain_community==0.3.2 langchain_openai -i https://mirrors.cloud.tencent.com/pypi/simple +``` + +:::tip +你也可以使用 [langchain javascript 版本](https://js.langchain.com/docs/introduction/) +::: + +使用 langchain `@tool` 装饰器,会自动帮你转换为符合规范的 tools 参数, +使用 langgraph `create_react_agent` 创建 agent, 将会自带生成函数调用、执行工具、回传工具消息等,极大简化流程。 +```python +from langchain_openai import ChatOpenAI +from langchain.tools import tool +from langchain_community.document_loaders import WebBaseLoader +from typing import AsyncIterator, Iterator, List, Optional, Annotated +from langgraph.prebuilt import create_react_agent +from langchain_core.messages import HumanMessage, AIMessage, AIMessageChunk, ToolMessage + + +@tool +def get_cctv_news(query: str): + """获取最新新闻列表、今日新闻。此工具提供热门新闻摘要、链接,有图片的信息还提供了封面""" + try: + # 通过 CCTV 新闻接口获取数据 (忽略 2019/07,设计如此, 实际上是最新的) + news_load = WebBaseLoader( + 'https://news.cctv.com/2019/07/gaiban/cmsdatainterface/page/news_1.jsonp?cb=news').load() + news = news_load[0].page_content + print('get_cctv_news 长度', len(news)) + # 截取字符, 防止过长、加快 AI 速度。 + return news[:4000] + except Exception as e: + print("get_cctv_news 失败", e) + +# 不安全 + + +@tool +def python_code_exec(code: Annotated[str, '安全的 python 代码、表达式,将结果赋值到变量 result 中。字符串是多行字符串']) -> dict: + """执行 python 代码、根据输入的表达式进行数学计算。可利用 python 编程解决的问题,你可以自由编写安全的、完整、可执行的 python 代码,获取执行结果""" + local_vars = {} + try: + exec(code, {}, local_vars) + return f"结果是: {str(local_vars)}" + except Exception as e: + return f"执行失败: {str(e)}" + + +tools_list = [get_cctv_news, python_code_exec] + + +model_name = "Qwen/Qwen2.5-72B-Instruct" +base_url = "https://ai.gitee.com/api/serverless/Qwen2.5-72B-Instruct" + +# https://ai.gitee.com/dashboard/settings/tokens 获取你的访问令牌 +Gitee_AI_API_KEY = "" + +llm = ChatOpenAI(model=model_name, api_key=Gitee_AI_API_KEY, base_url=base_url, streaming=True, temperature=0.1, presence_penalty=1.05, top_p=0.9, + extra_body={ + "tool_choice": "auto", + }) +system_message = """你是聪明的助手,在调用工具之前简单汇报""" + +# 使用 langgraph 创建 agent,自带调用、执行工具、回传工具消息等 +agent_executor = create_react_agent( + llm, tools=tools_list, debug=False) + +ai_res_msg = '' +first = True +config = {"configurable": {"thread_id": "xxx", "recursion_limit": 10}} + +for ai_msg, metadata in agent_executor.stream( + {"messages": [system_message, HumanMessage(content="汇报今日新闻")]}, config, stream_mode="messages" +): + if ai_msg.content and isinstance(ai_msg, AIMessage): + # 实时输出 + print(ai_msg.content, end="") + ai_res_msg += ai_msg.content + + if isinstance(ai_msg, AIMessageChunk): + if first: + gathered = ai_msg + first = False + else: + gathered = gathered + ai_msg + if ai_msg.tool_call_chunks: + print("调用的函数:", gathered.tool_calls) + if isinstance(ai_msg, ToolMessage): + print("ToolMessage", ai_msg.content) + +# 汇总输出 +print(ai_res_msg) +``` +你将会看到模型实时调用的过程和汇报结果! + diff --git a/sidebars.ts b/sidebars.ts index 50ed168..734c673 100644 --- a/sidebars.ts +++ b/sidebars.ts @@ -65,6 +65,10 @@ const sidebars: SidebarsConfig = { type: 'doc', id: 'serverless-api/integration', }, + { + type: 'doc', + id: "serverless-api/llm-chat" + } ], }, { diff --git a/src/css/custom.css b/src/css/custom.css index da002be..e2bcbfc 100644 --- a/src/css/custom.css +++ b/src/css/custom.css @@ -161,4 +161,9 @@ article[itemprop=blogPost] header h2 a { div[id^=headlessui-disclosure-panel] tr td.relative:nth-child(2) { position: inherit !important; +} + +/* 修正 tabs 样式 */ +.markdown li.tabs__item { + display: inline-flex; } \ No newline at end of file -- Gitee From 04f7e42680b701b593f0fe3fc0ed1542ab868278 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=A1=A3=E6=B2=BE=E4=B8=8D=E8=B6=B3=E6=83=9C?= Date: Wed, 13 Nov 2024 15:09:01 +0800 Subject: [PATCH 2/2] =?UTF-8?q?docs:=20=E6=B7=BB=E5=8A=A0=E5=A4=A7?= =?UTF-8?q?=E8=AF=AD=E8=A8=80=E6=A8=A1=E5=9E=8B=E5=AF=B9=E8=AF=9D=E6=95=99?= =?UTF-8?q?=E7=A8=8B=E3=80=81=E5=AE=9A=E5=88=B6=E8=A7=92=E8=89=B2=E3=80=81?= =?UTF-8?q?function=20call=E3=80=81=E6=9F=A5=E8=AF=A2=E6=96=B0=E9=97=BB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: 衣沾不足惜 --- .../{llm-chat.md => llm-chat.mdx} | 206 ++++++++++++++---- 1 file changed, 165 insertions(+), 41 deletions(-) rename docs/serverless-api/{llm-chat.md => llm-chat.mdx} (62%) diff --git a/docs/serverless-api/llm-chat.md b/docs/serverless-api/llm-chat.mdx similarity index 62% rename from docs/serverless-api/llm-chat.md rename to docs/serverless-api/llm-chat.mdx index 82069eb..799abd5 100644 --- a/docs/serverless-api/llm-chat.md +++ b/docs/serverless-api/llm-chat.mdx @@ -4,19 +4,14 @@ import Tabs from '@theme/Tabs'; import TabItem from '@theme/TabItem'; 摘要:本教程将带领你快速入门 Gitee AI 大语言模型 API: - - - - - +- [通过 curl 快速使用大模型能力](#通过-curl-快速使用大模型能力) +- [使用 openai 客户端调用 Gitee AI 模型 API](#使用-openai-客户端调用-gitee-ai-模型-api) +- [请求体常见参数说明](#请求体常见参数说明) +- [定制角色风格:如何让 AI 更懂你](#定制角色风格如何让-ai-更懂你) +- [调用函数!](#调用函数) +- [实战,让 AI 汇报今日新闻、执行 python 代码!](#实战让-ai-汇报今日新闻执行-python-代码) +- [让模型响应 JSON 格式数据](#让模型响应-json-格式数据) +- [下一步](#下一步) :::tip 前置条件: @@ -24,9 +19,9 @@ import TabItem from '@theme/TabItem'; 2. 二选一:[创建访问令牌](https://ai.gitee.com/stringify/dashboard/settings/tokens) 购买 [Serverless API](https://ai.gitee.com/serverless-api#%E6%96%87%E6%9C%AC%E7%94%9F%E6%88%90) 或 使用免费的临时 token ::: -## 通过 curl 快速使用大模型能力 {#通过curl快速使用大模型能力} +## 通过 curl 快速使用大模型能力 -一些框架、插件封装度较高,curl 可清晰了解请求的路径、参数的原始情况: +一些框架、插件封装度较高,curl 可清晰了解请求路径、参数的原始情况: @@ -50,6 +45,45 @@ import TabItem from '@theme/TabItem'; }' ``` + +```js +async function query(data) { + const response = await fetch( + "https://ai.gitee.com/api/serverless/Qwen2.5-72B-Instruct/chat/completions", + { + headers: { + "Authorization": "Bearer xxxxx", + "Content-Type": "application/json" + }, + method: "POST", + body: JSON.stringify(data), + } + ); + const result = await response.json(); + return result; +} + +query({ + "messages": [ + { + "role": "system", + "content": "你是聪明的助手" + }, + { + "role": "user", + "content": "老鼠生病了可以吃老鼠药治好吗?" + } + ], + "stream": false, + "max_tokens": 512, + "temperature": 0.7, + "top_p": 0.7, + "frequency_penalty": 1 +}).then((response) => { + console.log(JSON.stringify(response)); +}); +``` + AI 模型响应: @@ -90,7 +124,7 @@ Gitee AI 的 Serverless API 兼容开发者喜爱且社区流行的 OpenAI 风 以 openai 客户端为例,首先安装依赖:`pip install openai -i https://mirrors.cloud.tencent.com/pypi/simple` :::tip -如果你只熟悉 javascript 可使用 [openai nodejs 客户端](https://www.npmjs.com/package/openai/) +如果你有 javascript 经验可使用 [openai nodejs 客户端](https://www.npmjs.com/package/openai/) ::: app.py 文件如下: @@ -123,7 +157,7 @@ for chunk in completion: ``` -参数说明: +## 请求体常见参数说明 - model:指定要使用的模型名称,比如 "Qwen/Qwen2.5-72B-Instruct" 或 "01-ai/Yi-1.5-34B-Chat". - messages:消息列表,用于设置对话的上下文,每条消息包含 role 和 content。通过控制此列表,可实现多轮对话。这里的 messages 就是常说的 “prompt” 。 @@ -135,12 +169,25 @@ for chunk in completion: - temperature:用于控制生成内容的随机性,取值范围为 0-1。值越低,输出越稳定;值越高,输出越有创造性。 - top_p:值在 0-1 之间,控制生成内容的保守性或多样性。 - max_tokens:限制生成文本的长度,防止过长的回复。 -- stream:布尔值,将逐字响应,避免等待时间过长。 +- stream:布尔值,true 将逐字响应,避免等待时间过长。 - frequency_penalty:用于控制模型在生成内容时的重复程度。它的值在 -2.0 到 2.0 之间,建议设置 > 1。 - tools:用于定义工具列表, -- -## 定制你的个性化 AI -定制 AI 非常简单,你只需要在 role 为 system 的 content 中写入你的提示词即可: +- tool_choice: 支持 "auto" 由模型自动选择工具,也支持强制选择工具,写法如下: +```json +"tool_choice": {"type": "function", "function": {"name": "function_name"}}, +``` +- guided_json:让模型以指定的 JSON Schema 响应。不建议与 tools、guided_json 同时传入。 + +> JSON Schema 更多信息可参阅:[JSON Schema](https://json-schema.org/learn/miscellaneous-examples) +- guided_choice: 让模型选择提供的字符串列表之一,不建议与 tools、guided_json 同时传入。 + + 例如判断用户输入正负面性可传入: +```json +"guided_choice": ["正面", "负面", "中性"] +``` + +## 定制角色风格:如何让 AI 更懂你 +定制 AI 风格非常简单,你只需要在 role 为 system 的 content 中写入你的提示词即可: ```python completion = client.chat.completions.create( model=model_name, @@ -164,11 +211,14 @@ for chunk in completion: AI 回答: > 嘤嘤嘤~(⊙o⊙) 萌萌好心疼你呀!发生什么不开心的事情了吗?说出来让萌萌听听,抱抱你,让你的心情变好一点 ~~ (^_^) 一切都会好起来的,要加油鸭!(*^▽^*) -## 使用模型调用函数! +## 调用函数! “function call” 可调用自定义函数、外部工具、API 和数据源进行深度交互,极大提高 AI能力,是 “AI Agent” 概念的核心。 -注意:AI 并不被允许自行执行函数,而是由您定义函数,AI 再根据用户输入,向你提供是否需要调用、调用什么函数、提取哪些参数。 -由你得到 AI 的数据后自己执行。而一些框架,例如 LangGraph、LlamaIndex 可以简化这一过程。 +注意: + +AI 并不被允许自行执行函数,而是由您定义函数,AI 再根据用户输入,向你提供:是否需要调用、调用什么函数、函数参数。 + +由你得到 AI 的数据后自己执行函数。而一些框架,例如 LangGraph、LlamaIndex 可以简化这一过程。 :::tip “function call” 与 “tool call” 是类似概念,“tool call” 是升级版,已替代 “function call”。工具列表需要传入 tools。 @@ -207,14 +257,12 @@ tools = [ tools 是一个列表,可定义多个,参数说明: - type:定义参数对象的类型,通常是 object,表示参数结构为一个包含多个属性的 JSON 对象。 -- properties:这是核心部分,列出每个参数的具体定义。JSON Schema 格式。 +- properties:这是核心部分,列出每个参数的具体定义。[JSON Schema](https://json-schema.org/learn/miscellaneous-examples) 格式。 - name:每个属性的名称,对应函数的参数名。 - type:参数的数据类型,比如 string、float、integer 等。 - description:描述每个参数的用途,帮助模型理解如何填充参数值。 - required:指定哪些参数是必填的,如果参数在 required 列表中,那么模型在生成调用时必须填充这些参数。 -> JSON Schema 更多信息可参阅:[JSON Schema](https://json-schema.org/understanding-json-schema) - 将工具传入客户端中: ```python @@ -264,8 +312,8 @@ print(f"tool call 参数:", eval(f'{function_res.name}(**{arguments_res})') ``` -至此函数已成功调用!你可以将函数响应的结果,添加到 message 末尾: -```{'role': 'tool', 'name': 'get_current_weather', 'content': '抓取的数据: 北京当前温度:12°C天气状况:雾霾...', tool_call_id:'xxxx'}``` 再次请求 Gitee AI Serverless API,让 AI 整理答案。 +至此函数已成功调用!你可以将函数响应的结果处理为: +```{'role': 'tool', 'name': 'get_current_weather', 'content': '抓取的数据: 北京当前温度:12°C天气状况:雾霾...', tool_call_id:'xxxx'}``` 添加到 messages 消息列表末尾,再次请求 Gitee AI Serverless API,让 AI 整理答案。 上述方法为原始方法,用于理解 function call 流程和原理。接下来将使用更简便的方法实现。 @@ -280,8 +328,8 @@ pip install langchain==0.3.3 langgraph==0.2.38 langchain_core langchain_communit 你也可以使用 [langchain javascript 版本](https://js.langchain.com/docs/introduction/) ::: -使用 langchain `@tool` 装饰器,会自动帮你转换为符合规范的 tools 参数, -使用 langgraph `create_react_agent` 创建 agent, 将会自带生成函数调用、执行工具、回传工具消息等,极大简化流程。 +使用 langchain `@tool` 装饰器,会自动帮你转换为符合规范的 tools 参数,包括首行的 """xxx""" 注释和 Annotated 注释都会成为 tools 参数中的 "description"。 +使用 langgraph `create_react_agent` 创建 agent, 将会自动生成函数调用、执行工具、回传工具消息等,极大简化流程。 ```python from langchain_openai import ChatOpenAI from langchain.tools import tool @@ -290,27 +338,27 @@ from typing import AsyncIterator, Iterator, List, Optional, Annotated from langgraph.prebuilt import create_react_agent from langchain_core.messages import HumanMessage, AIMessage, AIMessageChunk, ToolMessage - +# 仅用于个人学习演示: @tool -def get_cctv_news(query: str): +def get_news(query: str): """获取最新新闻列表、今日新闻。此工具提供热门新闻摘要、链接,有图片的信息还提供了封面""" try: - # 通过 CCTV 新闻接口获取数据 (忽略 2019/07,设计如此, 实际上是最新的) news_load = WebBaseLoader( + # 忽略 2019/07,实际上是最新的 'https://news.cctv.com/2019/07/gaiban/cmsdatainterface/page/news_1.jsonp?cb=news').load() news = news_load[0].page_content - print('get_cctv_news 长度', len(news)) + print('get_news 长度', len(news)) # 截取字符, 防止过长、加快 AI 速度。 return news[:4000] except Exception as e: - print("get_cctv_news 失败", e) + print("get_news 失败", e) -# 不安全 +# 此函数存在安全隐患,仅用于演示,请勿用于生产环境: @tool def python_code_exec(code: Annotated[str, '安全的 python 代码、表达式,将结果赋值到变量 result 中。字符串是多行字符串']) -> dict: - """执行 python 代码、根据输入的表达式进行数学计算。可利用 python 编程解决的问题,你可以自由编写安全的、完整、可执行的 python 代码,获取执行结果""" + """执行 python 代码、根据输入的表达式进行数学计算。可利用 python 编程解决问题,你可以自由编写安全的、完整、可执行的 python 代码,然后获取执行结果""" local_vars = {} try: exec(code, {}, local_vars) @@ -319,7 +367,7 @@ def python_code_exec(code: Annotated[str, '安全的 python 代码、表达式 return f"执行失败: {str(e)}" -tools_list = [get_cctv_news, python_code_exec] +tools_list = [get_news, python_code_exec] model_name = "Qwen/Qwen2.5-72B-Instruct" @@ -359,10 +407,86 @@ for ai_msg, metadata in agent_executor.stream( if ai_msg.tool_call_chunks: print("调用的函数:", gathered.tool_calls) if isinstance(ai_msg, ToolMessage): - print("ToolMessage", ai_msg.content) + print("工具调用结果:", ai_msg.content) # 汇总输出 print(ai_res_msg) ``` -你将会看到模型实时调用的过程和汇报结果! +你将会看到模型实时调用的过程和最新新闻结果! + +## 让模型响应 JSON 格式数据 +通过 prompt 使模型响应 JSON,不稳定?现在你可以通过 guided_json 让模型以自定义的 [JSON Schema](https://json-schema.org/learn/miscellaneous-examples) 结构响应: + +```json +"guided_json": """{ + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "用户的姓名" + }, + "age": { + "type": "integer", + "description": "用户的年龄" + }, + "city": { + "type": "string", + "description": "用户的城市" + } + }, + "required": ["name", "age", "city"] + }""", +``` +再添加一些 prompt 提升可靠性,AI 将会根据输入提取数据生成标准的 JSON: + +```python +from langchain_openai import ChatOpenAI +model_name = "Qwen/Qwen2.5-72B-Instruct" +base_url = "https://ai.gitee.com/api/serverless/Qwen2.5-72B-Instruct" +# https://ai.gitee.com/dashboard/settings/tokens 获取你的访问令牌 +Gitee_AI_API_KEY = "" +llm = ChatOpenAI(model=model_name, api_key=Gitee_AI_API_KEY, base_url=base_url, streaming=True, temperature=0.1, presence_penalty=1.05, top_p=0.9, + extra_body={ + "guided_json": """{ + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "用户的姓名" + }, + "age": { + "type": "integer", + "description": "用户的年龄" + }, + "city": { + "type": "string", + "description": "用户的城市" + } + }, + "required": ["name", "city"] + }""" + }) + +prompt = [{"role": "system", "content": "你是聪明的助手,以 json 格式输出数据,如果无法判断年龄,则 age 为 0"}, + {"role": "user", "content": """ + 在一个风和日丽的春日午后,小马走在了北京的街头。时间是 2023年的4月15日, + 正值樱花盛开的季节。作为一位热爱摄影的年轻人,他带着相机,希望能捕捉到这个季节最美的瞬间。 + 北京的春天总是短暂而美丽,每一处公园、每一条街道都充满了生机与活力。 + """}] + +for response in llm.stream(prompt): + if (response.content): + print(response.content, end="") + +``` +输出 JSON: +```json +{ "name": "小马", "age": 0, "city": "北京" } +``` +## 下一步 +1. 你可以发挥创造,将大语言模型的能力与 Gitee AI 提供的其他 AI 能力结合,例如语音、图片、代码助手,并融合入你的产品! +2. 结合 API,[使用 CPU 创建一个在线 AI 应用](https://ai.gitee.com/apps/new) +3. 使用低代码平台、插件:例如 [dify](https://dify.ai/zh)、[沉浸式翻译](https://immersivetranslate.com/)、[lobehub](https://lobehub.com/zh?utm_source=gitee) 等 +4. 结合 UI 界面:使用 Gradio、Streamlit、Chainlit、OpenLLM 等 +5. 开发 [RAG 应用](https://ai.gitee.com/apps/lyworry/hanshizhuanjia/tree/master) 等 -- Gitee