6  ChatAnyWhere 服务

ChatAnyWhere 主要提供 OpenAI 大模型接入服务(也包括少量非 OpenAI 的模型)。

基本信息如下:

6.1 模型列表

ChatAnyWhere 提供的模型名字可能会与 OpenAI 不同。例如 *-ca 模型会有更优惠的价格。为了配置调用参数时写对模型名称,需要查询提供的模型列表。

library(httr)
library(glue)

# 读取 CHATANYWHERE_API_KEY 环境变量
OPENAI_API_KEY = Sys.getenv("CHATANYWHERE_API_KEY")

headers = c(
   'Authorization' = glue('Bearer {OPENAI_API_KEY}'),
   'User-Agent' = 'Apifox/1.0.0 (https://apifox.com)',
   'Content-Type' = 'application/json'
)

# 使用 GET 方法获取
res <- VERB("GET", 
            url = "https://api.chatanywhere.tech/v1/models", 
            add_headers(headers))

将 JSON 输出为表格。

library(jsonlite)
library(tidyverse)
library(gt)

models = jsonlite::fromJSON(content(res, as = "text", encoding = "UTF-8"))$data

models |> 
  mutate(created = as_datetime(created) |> as_date()) |> 
  gt(groupname_col = "owned_by")
id object created
openai-internal
text-embedding-ada-002 model 2022-12-16
gpt-3.5-turbo-16k model 2023-05-10
whisper-1 model 2023-02-27
tts-1 model 2023-04-19
system
text-embedding-3-small model 2024-01-22
text-embedding-3-large model 2024-01-22
gpt-3.5-turbo-0125 model 2024-01-23
gpt-3.5-turbo-1106 model 2023-11-02
gpt-3.5-turbo-instruct model 2023-08-24
gpt-3.5-turbo-instruct-0914 model 2023-09-07
gpt-4o model 2024-05-10
gpt-4o-2024-05-13 model 2024-05-10
chatgpt-4o-latest model 2024-05-10
gpt-4o-2024-08-06 model 2024-05-10
gpt-4o-mini model 2024-05-10
gpt-4o-mini-2024-07-18 model 2024-05-10
gpt-4-turbo model 2024-04-05
gpt-4-turbo-2024-04-09 model 2024-04-08
gpt-4-turbo-preview model 2024-01-23
gpt-4-1106-preview model 2023-11-02
gpt-4-0125-preview model 2024-01-23
gpt-4-vision-preview model 2023-11-02
gpt-4-1106-vision-preview model 2024-03-26
tts-1-1106 model 2023-11-03
tts-1-hd model 2023-11-03
tts-1-hd-1106 model 2023-11-03
dall-e-2 model 2023-11-01
dall-e-3 model 2023-10-31
ca
gpt-3.5-turbo-ca model 2024-01-23
gpt-4o-ca model 2024-01-23
gpt-4-turbo-ca model 2024-01-23
gpt-4-turbo-preview-ca model 2024-01-23
o1-mini-ca model 2024-01-23
o1-preview-ca model 2024-01-23
gpt-4-ca model 2023-03-12
claude-3-5-sonnet-20240620 model 2023-03-12
openai
gpt-3.5-turbo model 2023-02-28
gpt-3.5-turbo-0613 model 2023-06-12
gpt-3.5-turbo-0301 model 2023-03-01
gpt-3.5-turbo-16k-0613 model 2023-05-30
gpt-4 model 2023-03-12
gpt-4-0613 model 2023-06-12

下面依次介绍这些模型的用法。

6.2 对话模型

gpt-* 开头的都是文本对话模型。调用 OpenAI 的模型时,通常需要配置以下一些关键参数来控制模型的行为和生成结果的方式。

  1. Prompt(提示)
    • 模型的输入文本,通常称为“提示”。
    • 可以是简单的文本,或者带有一些问题或任务描述,告诉模型生成哪类内容。
  2. Max Tokens(最大令牌数)
    • 指定生成的文本中最多包含多少个令牌(tokens)。一个令牌大约对应一个英文单词或标点符号。
    • 该参数可以控制生成的响应长度,但包括输入和输出在内的令牌总数不能超过模型的上下文长度限制。
  3. Temperature(温度)
    • 控制生成文本的随机性。范围是 02
      • temperature=0 时,输出更加确定和保守,偏向生成常见的或“最可能”的答案。
      • 较高的 temperature 值(如 0.7)会让生成的内容更加随机和多样化。
  4. n(生成次数)
    • 控制生成多少个不同的响应。
    • n=1 只生成一个响应;n=2 会生成多个响应,适合比较或选择最合适的内容。

调用 OpenAI 模型时,通常需要设置 模型名称、提示、最大令牌数、温度、top-p、生成次数 等参数,视任务需求还可以调整 出现惩罚、频率惩罚、停止序列 等其他配置,以控制生成的内容质量和行为。

下面这个例子,展示了 ChatGPT 数不清楚“temperature”这个单词里面有几个字母“e”。

body = '{
   "model": "gpt-4o-mini",
   "messages": [
      {
         "role": "system",
         "content": "You are a helpful assistant."
      },
      {
         "role": "user",
         "content": "Temperature这个单词中含有几个字母e?"
      }
   ],
   "temperature": 2
}';

res <- VERB("POST", 
            url = "https://api.chatanywhere.tech/v1/chat/completions", 
            body = body, 
            add_headers(headers))

content(res, 'text', encoding = "UTF-8") |> 
  fromJSON() |> 
  str()
List of 7
 $ id                : chr "chatcmpl-ABwBJsmRdhuBlKfEHdMtFwwASkSpK"
 $ object            : chr "chat.completion"
 $ created           : int 1727408621
 $ model             : chr "gpt-4o-mini-2024-07-18"
 $ choices           :'data.frame': 1 obs. of  4 variables:
  ..$ index        : int 0
  ..$ message      :'data.frame':   1 obs. of  2 variables:
  .. ..$ role   : chr "assistant"
  .. ..$ content: chr "\"Temperature\"这个单词中有两个字母e。"
  ..$ logprobs     : logi NA
  ..$ finish_reason: chr "stop"
 $ usage             :List of 4
  ..$ prompt_tokens            : int 29
  ..$ completion_tokens        : int 13
  ..$ total_tokens             : int 42
  ..$ completion_tokens_details:List of 1
  .. ..$ reasoning_tokens: int 0
 $ system_fingerprint: chr "fp_1bb46167f9"

6.3 使用 OpenAI API

from openai import OpenAI
import os

# 创建 client
client = OpenAI(
    api_key=os.getenv("CHATANYWHERE_API_KEY"), # 如果您没有配置环境变量,请在此处用您的API Key进行替换
    base_url="https://api.chatanywhere.tech",  # 填写 openAI 服务的 base_url
)

# 生成对话
completion = client.chat.completions.create(
    model="gpt-4o-ca",
    messages=[
        {'role': 'system', 'content': 'You are a helpful assistant.'},
        {'role': 'user', 'content': '你是谁'}],
    temperature=0.8,
    top_p=0.8
    )

print(completion.choices[0].message.content)
我是一个由人工智能驱动的助手,旨在帮助你回答问题、提供信息和完成任务。有任何问题或需要帮助的地方,请随时告诉我!

6.3.1 解析文件

ChatAnyWhere 的服务器是不是不支持下面这个命令?

from pathlib import Path

assistant = client.beta.assistants.create(
  name="Document Reader Assistant",
  instructions="You are an document reader",
  model="gpt-4o",
  tools=[{"type": "file_search"}],
)

file_object = client.files.create(file=open(Path("example/Kraken2.pdf"),"r"), 
                                  purpose="assistants")

print(f"文件上传成功,文件ID: {file_object.id}")

6.3.2 使用 Kimi 服务器解析

from pathlib import Path
from openai import OpenAI
import os

client = OpenAI(
   api_key = os.getenv("MOONSHOT_API_KEY"),  # 替换为你的API密钥
   base_url = "https://api.moonshot.cn/v1",
)

pdf_file_path = Path("example/Kraken2.pdf")

# 上传文件
file_object = client.files.create(file = pdf_file_path, 
                                  purpose = "file-extract")

print(f"文件上传成功,文件ID: {file_object.id}")
文件上传成功,文件ID: crshkmalve9pdev71plg
# 获取文件内容
file_content = client.files.content(file_id=file_object.id).text

# 打印前 200 字
print(file_content[:200])
{"content":"利⽤宏基因组的reads进⾏物种注释的常⽤⼯具有很多,它们通过⽐对reads到参考数据库来识别微⽣物的分类信\n息。以下是⼏种常⽤的⼯具:\n1. Kraken2\n⼯作原理:基于k-mer⽐对技术,将reads⽐对到参考数据库中的特定k-mer集合,以实现快速的分类注\n释。\n优点:速度⾮常快,能处理⼤规模数据。\n数据库:Kraken2允许使⽤标准数据库(如NCBI 
from IPython.display import Markdown

messages = [
    {
        "role": "system",
        "content": "你是Kimi,由Moonshot AI提供的人工智能助手。"
    },
    {
        "role": "system",
        "content": file_content  # 将文件内容作为系统提示
    },
    {
        "role": "user",
        "content": "总结一下这份文件中的内容"
    }
]

# 发送对话请求
response = client.chat.completions.create(
    model="moonshot-v1-32k",
    messages=messages,
    temperature=0.3,
)

# 打印回答
Markdown(response.choices[0].message.content)

这份文件是关于如何使用宏基因组的reads进行物种注释的指南,主要介绍了几种常用的工具,包括Kraken2、MetaPhlAn3和Centrifuge。以下是对这些工具的总结:

  1. Kraken2
    • 工作原理:基于k-mer比对技术,将reads比对到参考数据库中的特定k-mer集合。
    • 优点:速度快,能处理大规模数据。
    • 数据库:可以使用标准数据库或自定义数据库。
    • 输出:物种分类信息和物种相对丰度。
    • Standard-8数据库:为资源有限的环境优化,数据库大小限制为8GB,针对常见物种优化,快速分析。
  2. MetaPhlAn3
    • 工作原理:使用已知微生物的标记基因进行比对。
    • 优点:适合分析物种相对丰度,计算效率高。
    • 数据库:使用MetaPhlAn自带的标记基因数据库。
    • 输出:物种分类和丰度表。
  3. Centrifuge
    • 工作原理:基于压缩索引技术,将reads与压缩参考数据库中的基因组序列进行比对。
    • 优点:处理大数据库速度快,适合处理低质量reads。
    • 数据库:使用Centrifuge提供的参考数据库或自定义数据库。
    • 输出:物种分类和丰度估计。

文件还提供了使用Kraken2进行宏基因组测序数据物种注释分析的步骤,包括安装Kraken2、下载数据库、运行Kraken2进行分类注释以及分析结果。此外,还提供了如何使用R语言的ggplot2库对分类结果进行可视化的示例代码。

最后,文件提供了一个Kraken2输出报告的示例,显示了样本中不同分类单元的相对丰度,并展示了如何使用R语言绘制分类结果的柱状图。

6.4 词嵌入模型

所有三个词嵌入模型都是基于 Transformer 架构,这使得它们在处理自然语言时具有良好的性能。下表比较了 text-embedding-ada-002text-embedding-3-smalltext-embedding-3-large 这三个词嵌入模型的特点:

模型名称 参数量 嵌入维度 性能 适用场景 优点 缺点
text-embedding-ada-002 中等 1536 高效,性能优秀 通用文本嵌入,适用于广泛的 NLP 任务 高精度嵌入,适合各种语义匹配任务 相比小型模型,计算资源需求较高
text-embedding-3-small 512 较快,资源效率高 资源受限的应用场景,低计算成本的嵌入生成 计算效率高,适合实时或资源有限的场景 嵌入维度较低,可能影响语义表达能力
text-embedding-3-large 2048 更高性能,精度极高 高端应用场景,如高精度语义搜索和推荐系统 嵌入维度更高,能够捕捉复杂语义关系 资源消耗大,适合计算资源充足的场景
body = '{
   "model": "text-embedding-ada-002",
   "input": "The food was delicious and the waiter..."
}';

res = VERB("POST", 
           url = "https://api.chatanywhere.tech/v1/embeddings", 
           body = body, 
           add_headers(headers))

content = content(res, 'text', encoding = "UTF-8")

embedding = fromJSON(content)
str(embedding)
List of 4
 $ object: chr "list"
 $ data  :'data.frame': 1 obs. of  3 variables:
  ..$ object   : chr "embedding"
  ..$ embedding:List of 1
  .. ..$ : num [1:1536] 0.00238 -0.00932 0.01569 -0.00774 -0.00472 ...
  ..$ index    : int 0
 $ model : chr "text-embedding-ada-002"
 $ usage :List of 3
  ..$ prompt_tokens    : int 8
  ..$ completion_tokens: int 0
  ..$ total_tokens     : int 8

6.5 文生图模型

dall-e-2dall-e-3 是文生图模型。

DALL-E 2 支持以下三种图像尺寸:

  1. 256x256
  2. 512x512
  3. 1024x1024

DALL-E 3 支持以下图像尺寸:

  1. 1024x1024: 正方形图像,适合大多数使用场景,是默认推荐的尺寸。
  2. 1792x1024: 宽屏图像,适合需要更宽视野的场景或横向布局的设计。
  3. 1024x1792: 纵向图像,适合需要更高视野的场景或纵向布局的设计。

你可以根据具体需求选择合适的图像尺寸进行生成。

url = "https://api.chatanywhere.tech/v1/images/generations"

body = '{
   "prompt": "A colorful sunset over the snow mountains",
   "n": 1,
   "model":  "dall-e-2",
   "size": "256x256"
}';

response = VERB("POST", url, body = body, add_headers(headers))

content = content(response, "text", encoding = "UTF-8")
print(content)
[1] "{\"created\":1727601271,\"data\":[{\"url\":\"https://oaidalleapiprodscus.blob.core.windows.net/private/org-iEnzkgXz3MLYFDoiaMsyPKYw/user-4vHAQk9cYlLmeDvsuy2iKvDZ/img-rtLChxv4kEKdWs8fWdKyHaLc.png?st=2024-09-29T08%3A14%3A31Z&se=2024-09-29T10%3A14%3A31Z&sp=r&sv=2024-08-04&sr=b&rscd=inline&rsct=image/png&skoid=d505667d-d6c1-4a0a-bac7-5c84a87759f8&sktid=a48cca56-e6da-484e-a814-9c849652bcb3&skt=2024-09-29T01%3A03%3A42Z&ske=2024-09-30T01%3A03%3A42Z&sks=b&skv=2024-08-04&sig=A2h8h/24EXYfTQXp4jrt2794eopKRKIQUypio0ccnNU%3D\"}]}"

获取图片。

# 获取生成的图像 URL
image_url = fromJSON(content)[["data"]][["url"]]

# 下载图片
response <- GET(image_url)

# 检查请求是否成功
if (status_code(response) == 200) {
  # 将图片保存到磁盘
  writeBin(content(response, "raw"), "output/sunset.png")
  cat("图片已成功保存到 `output/sunset.png`。")
} else {
  cat("下载图片失败,状态码:", status_code(response), "\n")
}

图片已成功保存到 output/sunset.png

6.6 识图功能(不支持)

使用多模态模型,可以识别图片中的信息。

# 设置请求体
body = list(
  model = "gpt-4o-ca",
  file = upload_file("output/sunset.png"),  # 文件路径
  prompt = "这是什么?",  # 提示
  encode = "multipart"
  )

res = VERB("POST", 
            url = "https://api.chatanywhere.tech/v1/chat/completions", 
            body = body, 
            add_headers(headers))

cat(content(res, 'text', encoding = "UTF-8"))
{"error":{"message":"JSON parse error: Unexpected character ('-' (code 45)) in numeric value: expected digit (0-9) to follow minus sign, for valid numeric value; nested exception is com.fasterxml.jackson.core.JsonParseException: Unexpected character ('-' (code 45)) in numeric value: expected digit (0-9) to follow minus sign, for valid numeric value\n at [Source: (org.springframework.util.StreamUtils$NonClosingInputStream); line: 1, column: 3]","type":"chatanywhere_error","param":null,"code":"400 BAD_REQUEST"}}

6.7 文字转语音模型

将一段文字转变为语音,支持中英文混合。

body = '{
   "model": "tts-1",
   "input": "今天天气不错。It is a nice day today.",
   "voice": "alloy"
}';

res <- VERB("POST", 
            url = "https://api.chatanywhere.tech/v1/audio/speech", 
            body = body, 
            add_headers(headers))

# 检查请求是否成功
if (status_code(res) == 200) {
  # 将响应保存为音频文件(假设返回的是二进制音频数据)
  audio_file <- "output/audio-goodday.mp3"  # 你可以更改文件名和扩展名
  writeBin(content(res, "raw"), audio_file)
  message("Audio saved successfully as: ", audio_file)
} else {
  message("Request failed with status: ", status_code(res))
}

6.8 语音识别模型

whisper-1 是 OpenAI 开发的一个强大的语音识别模型。它主要用于将语音转换为文本(也称为语音转文字,Speech-to-Text,简称 STT)。该模型能够处理多种语言的语音输入,并能够识别不同的口音和语音风格,非常适用于各种音频转录任务。

headers_multipart = c(
   'Authorization' = glue('Bearer {OPENAI_API_KEY}'),
   'User-Agent' = 'Apifox/1.0.0 (https://apifox.com)',
   'Content-Type' = 'multipart/form-data'
)

body = list(
   'file' = upload_file('output/audio-goodday.mp3'),
   'model' = 'whisper-1',
   'prompt' = 'eiusmod nulla',
   'response_format' = 'json',
   'temperature' = '0',
   'language' = ''
)

res = VERB("POST", 
            url = "https://api.chatanywhere.tech/v1/audio/transcriptions", 
            body = body, 
            add_headers(headers_multipart),
            encode = 'multipart')

cat(content(res, 'text', encoding = "UTF-8"))
{
  "text": "今年天氣不錯 It is a nice day today"
}

6.9 Claude 模型(无效)

ChatAnywhere 提供了一个 claude-3-5-sonnet-20240620 模型。

body = '{
   "model": "claude-3-5-sonnet-20240620",
   "messages": [
      {
         "role": "system",
         "content": "You are a helpful assistant."
      },
      {
         "role": "user",
         "content": "Temperature这个单词中含有几个字母e?"
      }
   ],
   "temperature": 2
}';

res <- VERB("POST", 
            url = "https://api.chatanywhere.tech/v1/chat/completions", 
            body = body, 
            add_headers(headers))

content(res, 'text', encoding = "UTF-8") |> 
  fromJSON() |> 
  str()
List of 1
 $ error:List of 4
  ..$ message: chr "模型无返回结果,可能是内容违规、输入过长、输入格式有误或负载较高,请检查后再试。No response, please try again."
  ..$ type   : chr "chatanywhere_error"
  ..$ param  : NULL
  ..$ code   : chr "503 SERVICE_UNAVAILABLE"

6.10 语音翻译模型(无效)

将音频翻译成英文。

body = list(
   'file' = upload_file('output/audio-goodday.mp3'),
   'model' = 'whisper-1',
   'prompt' = '',
   'response_format' = 'json',
   'temperature' = '0'
)

res <- VERB("POST", 
            url = "https://api.chatanywhere.tech/v1/audio/translations", 
            body = body, 
            add_headers(headers_multipart), 
            encode = 'multipart')

cat(content(res, 'text', encoding = "UTF-8"))
{
  "text": "今天天气不错。It is a nice day today."
}

6.11 用量查询(无效)

body = '{
   "model": "gpt-4o-mini",
   "hours": 24
}';

res <- VERB("POST", 
            url = "https://api.chatanywhere.tech/v1/query/usage_details", 
            body = body, 
            add_headers(headers))

cat(content(res, 'text', encoding = "UTF-8"))
{"error":{"message":"wrong api key","type":"chatanywhere_error","param":null,"code":"401 UNAUTHORIZED"}}

6.12 自动补全(无效)

文档里说:“给定一个提示,该模型将返回一个或多个预测的完成,并且还可以返回每个位置的替代标记的概率”。但是,实际上这个接口不可用。

body = '{
   "model": "gpt-4o-mini",
   "prompt": "Say this is a test",
   "max_tokens": 7,
   "temperature": 0,
   "top_p": 1,
   "n": 1,
   "stream": false,
   "logprobs": null,
   "stop": "\\n"
}';

res <- VERB("POST", url = "https://api.chatanywhere.tech/v1/completions", 
            body = body, 
            add_headers(headers))

# 优雅地输出 JSON
content(res, 'text', encoding = 'UTF-8') |> 
  jsonlite::prettify()
{
    "error": {
        "message": "This is a chat model and not supported in the v1/completions endpoint. Did you mean to use v1/chat/completions?",
        "type": "invalid_request_error",
        "param": "model",
        "code": null
    }
}