Langchain-Chatchat/docs/contributing/api.md

308 lines
22 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

## 常用 API 接口调用方式
### 说明
所有接口可以到 `{api_address}/docs` 中查看参数和测试。
### /tools
该接口列出所有工具及其参数信息。
输入参数:无
输出示例:
```
{
"code": 200,
"msg": "success",
"data": {
"search_local_knowledgebase": {
"name": "search_local_knowledgebase",
"title": "本地知识库",
"description": "Use local knowledgebase from one or more of these: test: 关于test的知识库 samples: 关于本项目issue的解答 to get informationOnly local data on this knowledge use this tool. The 'database' should be one of the above [test samples].",
"args": {
"database": {
"title": "Database",
"description": "Database for Knowledge Search",
"choices": [
"test",
"samples"
],
"type": "string"
},
"query": {
"title": "Query",
"description": "Query for Knowledge Search",
"type": "string"
}
},
"config": {
"use": false,
"top_k": 3,
"score_threshold": 1,
"conclude_prompt": {
"with_result": "<指令>根据已知信息,简洁和专业的来回答问题。如果无法从中得到答案,请说 \"根据已知信息无法回答该问题\",不允许在答案中添加编造成分,答案请使用中文。 </指令>\n<已知信息>{{ context }}</已知信息>\n<问题>{{ question }}</问题>\n",
"without_result": "请你根据我的提问回答我的问题:\n{{ question }}\n请注意你必须在回答结束后强调你的回答是根据你的经验回答而不是参考资料回答的。\n"
}
}
},
...
}
}
```
### 通用对话接口(/chat/chat/completions
最主要的对话接口,兼容 openai sdk 格式。它支持以下3种对话模式
- 纯 LLM 对话。传入 `model`, `messages` 参数即可,可选参数: `temperature`, `max_tokens`, `stream` 等。
- Agent 对话。在 LLM 对话的基础上,传入 `tools` 参数,可以让 LLM 选择合适的工具和参数,作为对话的参考。
- 半 Agent 对话。在 LLM 对话的基础上,传入 `tool_choice` 参数,可以让 LLM 解析参数,直接调用指定的工具,作为对话的参考。如果使用的 LLM 解析参数的效果不理想,也可以手动指定工具参数。
输入参数:与 openai sdk 参数一致。针对 chatchat 做了以下优化:
- `tools` 参数可以使用 chatchat 中编写的工具名称,所有支持的工具可以通过 `/tools` 接口获取。
- 在指定 `tool_choice` 的情况下,可以在 `extra_body` 中传入 `tool_input={...}` 来手动指定工具参数。
- 使用 Agent 功能时,`stream` 参数必须指定为 `True`。因为 Agent 是分步执行的,必须通过 SSE 把每个步骤逐一输出。注意:此时 SSE 的单元是执行步骤LLM 的输出是非流式的。
调用示例:
- 纯 LLM 对话:
```python3
base_url = "http://127.0.0.1:7861/chat"
data = {
"model": "qwen1.5-chat",
"messages": [
{"role": "user", "content": "你好"},
{"role": "assistant", "content": "你好,我是人工智能大模型"},
{"role": "user", "content": "请用100字左右的文字介绍自己"},
],
"stream": True,
"temperature": 0.7,
}
# 方式一:使用 requests
import requests
response = requests.post(f"{base_url}/chat/completions", json=data, stream=True)
for line in response.iter_content(None, decode_unicode=True):
print(line, end="", flush=True)
# 方式二:使用 openai sdk
import openai
client = openai.Client(base_url=base_url, api_key="EMPTY")
resp = client.chat.completions.create(**data)
for r in resp:
print(r)
```
```shell
# 方式一输出SSE 格式
data: {"id":"chat6aa251c3-3425-11ef-be81-603a7c6af450","choices":[{"delta":{"content":"","function_call":null,"role":"assistant","tool_calls":null},"finish_reason":null,"index":0,"logprobs":null}],"created":1719452077,"model":"qwen1.5-chat","object":"chat.completion.chunk","system_fingerprint":null,"usage":null,"message_id":null,"status":null}
data: {"id":"chat6aa251c3-3425-11ef-be81-603a7c6af450","choices":[{"delta":{"content":"我是","function_call":null,"role":null,"tool_calls":null},"finish_reason":null,"index":0,"logprobs":null}],"created":1719452077,"model":"qwen1.5-chat","object":"chat.completion.chunk","system_fingerprint":null,"usage":null,"message_id":null,"status":null}
data: {"id":"chat6abf605c-3425-11ef-9f15-603a7c6af450","choices":[{"delta":{"content":"阿里云","function_call":null,"role":null,"tool_calls":null},"finish_reason":null,"index":0,"logprobs":null}],"created":1719452078,"model":"qwen1.5-chat","object":"chat.completion.chunk","system_fingerprint":null,"usage":null,"message_id":null,"status":null}
data: {"id":"chat6ad00242-3425-11ef-af45-603a7c6af450","choices":[{"delta":{"content":"自主研发的","function_call":null,"role":null,"tool_calls":null},"finish_reason":null,"index":0,"logprobs":null}],"created":1719452078,"model":"qwen1.5-chat","object":"chat.completion.chunk","system_fingerprint":null,"usage":null,"message_id":null,"status":null}
...
```
```shell
# 方式二输出:
ChatCompletionChunk(id='chat682070c8-3426-11ef-947d-603a7c6af450', choices=[Choice(delta=ChoiceDelta(content='', function_call=None, role='assistant', tool_calls=None), finish_reason=None, index=0, logprobs=None)], created=1719452503, model='qwen1.5-chat', object='chat.completion.chunk', system_fingerprint=None, usage=None, message_id=None, status=None)
ChatCompletionChunk(id='chat682070c8-3426-11ef-947d-603a7c6af450', choices=[Choice(delta=ChoiceDelta(content='我是', function_call=None, role=None, tool_calls=None), finish_reason=None, index=0, logprobs=None)], created=1719452503, model='qwen1.5-chat', object='chat.completion.chunk', system_fingerprint=None, usage=None, message_id=None, status=None)
ChatCompletionChunk(id='chat683fdd72-3426-11ef-be33-603a7c6af450', choices=[Choice(delta=ChoiceDelta(content='由阿里', function_call=None, role=None, tool_calls=None), finish_reason=None, index=0, logprobs=None)], created=1719452503, model='qwen1.5-chat', object='chat.completion.chunk', system_fingerprint=None, usage=None, message_id=None, status=None)
ChatCompletionChunk(id='chat68511ba1-3426-11ef-b2be-603a7c6af450', choices=[Choice(delta=ChoiceDelta(content='云开发', function_call=None, role=None, tool_calls=None), finish_reason=None, index=0, logprobs=None)], created=1719452503, model='qwen1.5-chat', object='chat.completion.chunk', system_fingerprint=None, usage=None, message_id=None, status=None)
...
```
- Agent 对话
以下示例仅展示使用 `requests` 的情况,可以自行尝试使用 `openai sdk` 进行请求,参数和输出内容是一样的。
```python3
base_url = "http://127.0.0.1:7861/chat"
tools = list(requests.get(f"http://127.0.0.1:7861/tools").json()["data"])
data = {
"model": "qwen1.5-chat",
"messages": [
{"role": "user", "content": "37+48="},
],
"stream": True,
"temperature": 0.7,
"tools": tools,
}
import requests
response = requests.post(f"{base_url}/chat/completions", json=data, stream=True)
for line in response.iter_content(None, decode_unicode=True):
print(line)
```
```shell
# 输出:
data: {"id": "chat39830df6-d016-4b91-b502-e113bb71542c", "object": "chat.completion.chunk", "model": "qwen1.5-chat", "created": 1719453364, "status": 1, "message_type": 1, "message_id": null, "is_ref": false, "choices": [{"delta": {"content": "", "tool_calls": []}, "role": "assistant"}]}
data: {"id": "chatb05f9cb2-1e93-4657-806b-29ec135483b9", "object": "chat.completion.chunk", "model": "qwen1.5-chat", "created": 1719453367, "status": 3, "message_type": 1, "message_id": null, "is_ref": false, "choices": [{"delta": {"content": "Thought: The problem involves adding two numbers: 37 and 48. To perform this calculation, I will use the calculator API.\nAction: calculate\nAction Input: {\"text\": \"37 + 48\"}", "tool_calls": []}, "role": "assistant"}]}
data: {"id": "chat73adade0-b62f-412a-a448-9002a59cbc30", "object": "chat.completion.chunk", "model": "qwen1.5-chat", "created": 1719453367, "status": 4, "message_type": 1, "message_id": null, "is_ref": false, "choices": [{"delta": {"content": "Thought: The problem involves adding two numbers: 37 and 48. To perform this calculation, I will use the calculator API.\nAction: calculate\nAction Input: {\"text\": \"37 + 48\"}", "tool_calls": []}, "role": "assistant"}]}
data: {"id": "chat7752232b-7360-4010-bc55-e50fa8ac9f44", "object": "chat.completion.chunk", "model": "qwen1.5-chat", "created": 1719453367, "status": 6, "message_type": 1, "message_id": null, "is_ref": false, "choices": [{"delta": {"content": "", "tool_calls": [{"index": 0, "id": "f2b20744-3958-4e3b-9e51-c5738d87a020", "type": "function", "function": {"name": "calculate", "arguments": "{'text': '37 + 48'}"}, "tool_output": null, "is_error": false}]}, "role": "assistant"}]}
data: {"id": "chatef5f948e-4772-477d-823d-ce74b38ba586", "object": "chat.completion.chunk", "model": "qwen1.5-chat", "created": 1719453367, "status": 7, "message_type": 1, "message_id": null, "is_ref": false, "choices": [{"delta": {"content": "", "tool_calls": [{"index": 0, "id": "f2b20744-3958-4e3b-9e51-c5738d87a020", "type": "function", "function": {"name": "calculate", "arguments": "{'text': '37 + 48'}"}, "tool_output": "85", "is_error": false}]}, "role": "assistant"}]}
data: {"id": "chatdee106c6-42e6-41cf-b2df-692431829e4d", "object": "chat.completion.chunk", "model": "qwen1.5-chat", "created": 1719453367, "status": 1, "message_type": 1, "message_id": null, "is_ref": false, "choices": [{"delta": {"content": "", "tool_calls": []}, "role": "assistant"}]}
data: {"id": "chat819ef11b-576f-4489-b6bb-47565eb69ee8", "object": "chat.completion.chunk", "model": "qwen1.5-chat", "created": 1719453370, "status": 3, "message_type": 1, "message_id": null, "is_ref": false, "choices": [{"delta": {"content": " The calculation 37 + 48 has been successfully performed using the calculate API, resulting in the result of 85. Therefore, the final answer to the given question is 85. \n\nJSON Object:\n{\n \"answer\": 85\n}", "tool_calls": []}, "role": "assistant"}]}
data: {"id": "chatb6b1071b-5346-4713-922c-b2887728491f", "object": "chat.completion.chunk", "model": "qwen1.5-chat", "created": 1719453370, "status": 5, "message_type": 1, "message_id": null, "is_ref": false, "choices": [{"delta": {"content": " The calculation 37 + 48 has been successfully performed using the calculate API, resulting in the result of 85. Therefore, the final answer to the given question is 85. \n\nJSON Object:\n{\n \"answer\": 85\n}", "tool_calls": []}, "role": "assistant"}]}
```
输出中包含一个 `status` 字段,代表 Agent 当前执行阶段。在 `status` 为 6 和 7 的输出中,可以看到 tool_call 的相关信息。具体值为:
```python3
class AgentStatus:
llm_start: int = 1
llm_new_token: int = 2
llm_end: int = 3
agent_action: int = 4
agent_finish: int = 5
tool_start: int = 6
tool_end: int = 7
error: int = 8
```
输出中包含一个 `message_type` 字段,代表输出内容的类型,主要用于前端渲染不同的消息,当前除了`text2image` 工具是 `IMAGE`,其它都是 `TEXT`。具体值为:
```python3
class MsgType:
TEXT = 1
IMAGE = 2
AUDIO = 3
VIDEO = 4
```
- 知识库对话LLM 自动解析参数)
直接指定 `tool_choice``"search_local_knowledgebase"`工具即可使用知识库对话功能。其它工具对话类似。
```python3
base_url = "http://127.0.0.1:7861/chat"
data = {
"messages": [
{"role": "user", "content": "如何提问以获得高质量答案"},
],
"model": "qwen1.5-chat",
"tool_choice": "search_local_knowledgebase",
"stream": True,
}
import requests
response = requests.post(f"{base_url}/chat/completions", json=data, stream=True)
for line in response.iter_content(None, decode_unicode=True):
print(line)
```
`status` 为 6 和 7 的返回值中,可以获取工具的调用和输出信息。
由于输出信息太多,这里不做展示,请自行测试。
- 知识库对话(手动传入参数)
直接指定 `tool_choice``"search_local_knowledgebase"`,再通过 `tool_input` 设定工具参数,即可手动调用工具,实现指定知识库对话。
```python3
base_url = "http://127.0.0.1:7861/chat"
data = {
"messages": [
{"role": "user", "content": "如何提问以获得高质量答案"},
],
"model": "qwen1.5-chat",
"tool_choice": "search_local_knowledgebase",
"tool_input": {"database": "samples", "query": "如何提问以获得高质量答案"},
"stream": True,
}
import requests
response = requests.post(f"{base_url}/chat/completions", json=data, stream=True)
for line in response.iter_content(None, decode_unicode=True):
print(line)
```
在输出中可以看出 `status` 为 6 和 7 的工具解析过程已经不存在了,说明工具调用不是通过 LLM 完成的。
由于输出信息太多,这里不做展示,请自行测试。
### RAG 接口 /knowledge_base/chat/compleitons
相比于 /chat/chat/completions 接口,本接口主要用于 RAG支持更多的参数其返回值也是 openai sdk 兼容的。除了 openai.chat.completions 规定的参数,还支持以下参数:
- mode检索模式
- "local_kb" 检索本地知识库,需提供 "kb_name" 指定知识库名称
- "temp_kb" 文件对话,需提供 "knowledge_id" 指定文件对话的临时知识库 ID
- "search_engine" 使用搜索引擎,需提供 "search_engine_name" 指定使用的搜索引擎
- top_k: 检索结果数量
- score_threshold: 匹配分值阈值
- prompt_name: 使用的 prompt 模板名称
- return_direct: 如果为 True则仅返回检索结果不经由 LLM
- messages: messages[-1]["content"] 将作为检索对象messages[:-1] 将作为 history
返回值:
- stream 为 True 时,第一个 ChatCompletionChunk.docs 包含检索结果
- stream 为 False 时ChatCompletion.docs 包含检索结果
调用示例(这里使用 openai sdk 演示本地知识库问答的情况requests 参数相同,只是把 extra_body 中的内容放到 data 里即可):
- 本地知识库问答
```python3
base_url = "http://127.0.0.1:7861/knowledge_base/local_kb/samples"
data = {
"model": "qwen2-instruct",
"messages": [
{"role": "user", "content": "你好"},
{"role": "assistant", "content": "你好,我是人工智能大模型"},
{"role": "user", "content": "如何高质量提问?"},
],
"stream": True,
"temperature": 0.7,
"extra_body": {
"top_k": 3,
"score_threshold": 2.0,
"return_direct": True,
},
}
import openai
client = openai.Client(base_url=base_url, api_key="EMPTY")
resp = client.chat.completions.create(**data)
for r in resp:
print(r)
```
输出示例:
```shell
ChatCompletionChunk(id='chat9973e445-8581-45ca-bde5-148fc724b30b', choices=[Choice(delta=None, finish_reason=None, index=None, logprobs=None, message={'role': 'assistant', 'content': '', 'finish_reason': 'stop', 'tool_calls': []})], created=1720592802, model=None, object='chat.completion', service_tier=None, system_fingerprint=None, usage=None, status=None, message_type=1, message_id=None, is_ref=False, docs=['出处 [1] [test_files/test.txt](http://127.0.0.1:7861//knowledge_base/download_doc?knowledge_base_name=samples&file_name=test_files%2Ftest.txt) \n\n[这就是那幅名画]: http://yesaiwen.com/art\nof\nasking\nchatgpt\nfor\nhigh\nquality\nansw\nengineering\ntechniques/#i\n3\t"《如何向ChatGPT提问并获得高质量的答案》"\n\n', '出处 [2] [test_files/test.txt](http://127.0.0.1:7861//knowledge_base/download_doc?knowledge_base_name=samples&file_name=test_files%2Ftest.txt) \n\nChatGPT是OpenAI开发的一个大型语言模型可以提供各种主题的信息\n# 如何向 ChatGPT 提问以获得高质量答案:提示技巧工程完全指南\n## 介绍\n我很高兴欢迎您阅读我的最新书籍《The Art of Asking ChatGPT for High-Quality Answers: A complete Guide to Prompt Engineering Techniques》。本书是一本全面指南介绍了各种提示技术用于从ChatGPT中生成高质量的答案。\n我们将探讨如何使用不同的提示工 程技术来实现不同的目标。ChatGPT是一款最先进的语言模型能够生成类似人类的文本。然而理解如何正确地向ChatGPT提问以获得我们所需的高质量输出非常重要。而这正是 本书的目的。\n无论您是普通人、研究人员、开发人员还是只是想在自己的领域中将ChatGPT作为个人助手的人本书都是为您编写的。我使用简单易懂的语言提供实用的解释并在每个提示技术中提供了示例和提示公式。通过本书您将学习如何使用提示工程技术来控制ChatGPT的输出并生成符合您特定需求的文本。\n在整本书中我们还提供了如何结合不同的提示技术以实现更具体结果的示例。我希望您能像我写作时一样享受阅读本书并从中获得知识。\n<div style="page\nbreak\nafter:always;"></div>\n## 第一章Prompt 工程技术简介\n什么是 Prompt 工程?\nPrompt 工程是创建提示或指导像 ChatGPT 这样的语言模型输出的过程。它允许用户控制模型的输出并生成符合其特定需求的文本。\n\n', '出处 [3] [test_files/test.txt](http://127.0.0.1:7861//knowledge_base/download_doc?knowledge_base_name=samples&file_name=test_files%2Ftest.txt) \n\nPrompt 公式是提示的特定格式,通常由三个主要元素组成:**\n任务对提示要求模型生成的内容进行清晰而简洁的陈述。\n指令在生成文本时模型应遵循的指令。\n角色模型在生成文本时应扮演的角色。\n在本书中我们将探讨可用于 ChatGPT 的各种 Prompt 工程技术。我们将讨论不同类型的提示,以及如何使用它们实现您想要的特定目标。\n<div style="page\nbreak\nafter:always;"></div>\n## 第二章:指令提示技术\n现在让我们开始探索“指令提示技术”以及如何使用它从ChatGPT中生成高质量的文本。\n 指令提示技术是通过为模型提供具体指令来引导ChatGPT的输出的一种方法。这种技术对于确保输出相关和高质量非常有用。\n要使用指令提示技术您需要为模型提供清晰简洁的任务以及具体的指令以供模型遵循。\n例如如果您正在生成客户服务响应您将提供任务例如“生成响应客户查询”的指令例如“响应应该专业且提供准确的信息”。\n 提示公式:“按照以下指示生成[任务][指令]”\n示例\n生成客户服务响应**\n任务生成响应客户查询\n指令响应应该专业且提供准确的信息\n提示公式“按照以下 指示生成专业且准确的客户查询响应:响应应该专业且提供准确的信息。”\n生成法律文件**\n任务生成法律文件\n指令文件应符合相关法律法规\n提示公式“按照以下 指示生成符合相关法律法规的法律文件:文件应符合相关法律法规。”\n使用指令提示技术时重要的是要记住指令应该清晰具体。这将有助于确保输出相关和高质量。可以将指 令提示技术与下一章节中解释的“角色提示”和“种子词提示”相结合以增强ChatGPT的输出。\n\n'])
```
- 文件对话
```python3
# knowledge_id 为 /knowledge_base/upload_temp_docs 的返回值
base_url = "http://127.0.0.1:7861/knowledge_base/temp_kb/{knowledge_id}"
data = {
"model": "qwen2-instruct",
"messages": [
{"role": "user", "content": "你好"},
{"role": "assistant", "content": "你好,我是人工智能大模型"},
{"role": "user", "content": "如何高质量提问?"},
],
"stream": True,
"temperature": 0.7,
"extra_body": {
"top_k": 3,
"score_threshold": 2.0,
"return_direct": True,
},
}
import openai
client = openai.Client(base_url=base_url, api_key="EMPTY")
resp = client.chat.completions.create(**data)
for r in resp:
print(r)
```
- 搜索引擎问答
```python3
engine_name = "bing" # 可选值bing, duckduckgo, metaphor, searx
base_url = f"http://127.0.0.1:7861/knowledge_base/search_engine/{engine_name}"
data = {
"model": "qwen2-instruct",
"messages": [
{"role": "user", "content": "你好"},
{"role": "assistant", "content": "你好,我是人工智能大模型"},
{"role": "user", "content": "如何高质量提问?"},
],
"stream": True,
"temperature": 0.7,
"extra_body": {
"top_k": 3,
"score_threshold": 2.0,
"return_direct": True,
},
}
import openai
client = openai.Client(base_url=base_url, api_key="EMPTY")
resp = client.chat.completions.create(**data)
for r in resp:
print(r)
```