17  ChatAnyWhere 服务

ChatAnyWhere 主要提供 OpenAI、Claude、Gemini 等国外闭源大模型接入服务。

基本信息如下:

17.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)

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

models |> 
  arrange(desc(owned_by), id) |> 
  mutate(created = as_datetime(created) |> as_date()) |> 
  kableExtra::kable()
id object created owned_by
chatgpt-4o-latest model 2024-05-10 system
chatgpt-4o-latest-ca model 2024-05-10 system
dall-e-2 model 2023-11-01 system
dall-e-3 model 2023-10-31 system
gpt-3.5-turbo-0125 model 2024-01-23 system
gpt-3.5-turbo-1106 model 2023-11-02 system
gpt-3.5-turbo-instruct model 2023-08-24 system
gpt-3.5-turbo-instruct-0914 model 2023-09-07 system
gpt-4-0125-preview model 2024-01-23 system
gpt-4-1106-preview model 2023-11-02 system
gpt-4-turbo model 2024-04-05 system
gpt-4-turbo-2024-04-09 model 2024-04-08 system
gpt-4-turbo-preview model 2024-01-23 system
gpt-4o model 2024-05-10 system
gpt-4o-2024-05-13 model 2024-05-10 system
gpt-4o-2024-08-06 model 2024-05-10 system
gpt-4o-2024-11-20 model 2024-05-10 system
gpt-4o-audio-preview model 2024-05-10 system
gpt-4o-audio-preview-2024-10-01 model 2024-05-10 system
gpt-4o-mini model 2024-05-10 system
gpt-4o-mini-2024-07-18 model 2024-05-10 system
gpt-4o-mini-2024-07-18-ca model 2024-05-10 system
gpt-4o-mini-ca model 2024-05-10 system
text-embedding-3-large model 2024-01-22 system
text-embedding-3-small model 2024-01-22 system
tts-1-1106 model 2023-11-03 system
tts-1-hd model 2023-11-03 system
tts-1-hd-1106 model 2023-11-03 system
gpt-3.5-turbo-16k model 2023-05-10 openai-internal
text-embedding-ada-002 model 2022-12-16 openai-internal
tts-1 model 2023-04-19 openai-internal
whisper-1 model 2023-02-27 openai-internal
gpt-3.5-turbo model 2023-02-28 openai
gpt-3.5-turbo-16k-0613 model 2023-05-30 openai
gpt-4 model 2023-03-12 openai
gpt-4-0613 model 2023-06-12 openai
claude-3-5-haiku-20241022 model 2023-03-12 ca
claude-3-5-sonnet-20240620 model 2023-03-12 ca
claude-3-5-sonnet-20241022 model 2023-03-12 ca
deepseek-reasoner model 2024-01-23 ca
gemini-1.5-flash-latest model 2023-03-12 ca
gemini-1.5-pro-latest model 2023-03-12 ca
gemini-2.0-flash model 2023-03-12 ca
gemini-2.0-flash-exp model 2023-03-12 ca
gemini-2.0-flash-thinking-exp model 2023-03-12 ca
gemini-2.0-pro-exp-02-05 model 2023-03-12 ca
gemini-exp-1206 model 2023-03-12 ca
gpt-3.5-turbo-ca model 2024-01-23 ca
gpt-4-ca model 2023-03-12 ca
gpt-4-turbo-ca model 2024-01-23 ca
gpt-4-turbo-preview-ca model 2024-01-23 ca
gpt-4o-ca model 2024-01-23 ca
o1 model 2024-01-23 ca
o1-2024-12-17 model 2024-01-23 ca
o1-mini model 2024-01-23 ca
o1-mini-2024-09-12 model 2024-01-23 ca
o1-mini-ca model 2024-01-23 ca
o1-preview model 2024-01-23 ca
o1-preview-2024-09-12 model 2024-01-23 ca
o1-preview-ca model 2024-01-23 ca
o3-mini model 2024-01-23 ca
o3-mini model 2024-01-23 ca

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

17.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-B2EwCpPaf2ogu7rCBvY18JrNcfXrT"
 $ 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"
 $ created           : int 1739873776
 $ model             : chr "gpt-4o-mini-2024-07-18"
 $ object            : chr "chat.completion"
 $ usage             :List of 5
  ..$ prompt_tokens            : int 29
  ..$ completion_tokens        : int 15
  ..$ total_tokens             : int 44
  ..$ completion_tokens_details:List of 2
  .. ..$ audio_tokens    : int 0
  .. ..$ reasoning_tokens: int 0
  ..$ prompt_tokens_details    :List of 2
  .. ..$ audio_tokens : int 0
  .. ..$ cached_tokens: int 0
 $ system_fingerprint: chr "fp_b045b4af17"

17.3 使用 OpenAI API

OpenAI 的原生 API 使用 Python 语言,以下是使用 Python 的示例代码。

from openai import OpenAI
import os
from IPython.display import Markdown

# 创建 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
    )

Markdown(completion.choices[0].message.content)

我是一个人工智能助手,旨在为你提供帮助、回答问题、解决问题或陪你聊天!你可以叫我助手,或者随便给我取个名字哦~有什么我可以帮你的吗?

在 R 中,ellmer 包主要用于构建和管理 LLM 交互,你可以使用 ellmer 达到类似的效果。以下是等效的 R 代码:

library(ellmer)

# 创建客户端
client <- chat_openai(
  api_key = Sys.getenv("CHATANYWHERE_API_KEY"), # 也可以直接填入 API Key
  system_prompt = "You are a helpful assistant.",
  base_url = "https://api.chatanywhere.tech",
  model = "gpt-4o-ca"
)

# 生成对话
client$chat("你是谁")
我是一个人工智能助手,可以用来回答问题、提供建议并协助你处理各种任务。有任何需要帮助的地方,请随时告诉我!😊

这段代码使用 ellmer 包的 OpenAIClient 进行 API 调用,chat_completions_create() 生成对话,与 Python 代码的逻辑基本一致。

17.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 更高性能,精度极高 高端应用场景,如高精度语义搜索和推荐系统 嵌入维度更高,能够捕捉复杂语义关系 资源消耗大,适合计算资源充足的场景

用 R 语言调用词嵌入模型。

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.00231 -0.00933 0.0158 -0.00778 -0.00469 ...
  ..$ index    : int 0
 $ model : chr "ada"
 $ usage :List of 2
  ..$ prompt_tokens: int 8
  ..$ total_tokens : int 8

等效的 Python 代码如下:

import requests
import json
import os

# API 端点和密钥
url = "https://api.chatanywhere.tech/v1/embeddings"
headers = {
    "Authorization": f"Bearer {os.getenv('CHATANYWHERE_API_KEY')}",
    "Content-Type": "application/json"
}

# 请求体
data = {
    "model": "text-embedding-ada-002",
    "input": "The food was delicious and the waiter..."
}

# 发送请求
response = requests.post(url, headers=headers, json=data)

# 解析响应
embedding = response.json()
print(len(embedding["data"][0]["embedding"]))
1536

这个 Python 版本使用 requests 发送 POST 请求,并解析返回的 JSON,效果和你的 R 代码相同。

可以使用 openai 模块,代码会更简洁:

from openai import OpenAI
from pprint import pprint
import os

client = OpenAI(api_key=os.getenv("CHATANYWHERE_API_KEY"), base_url="https://api.chatanywhere.tech")

response = client.embeddings.create(model="text-embedding-ada-002", input="The food was delicious and the waiter...")

pprint(response.dict(), depth=3)  # 以字典格式输出
{'data': [{'embedding': [...], 'index': 0, 'object': 'embedding'}],
 'model': 'ada',
 'object': 'list',
 'usage': {'prompt_tokens': 8, 'total_tokens': 8}}

17.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-3",
   "size": "1792x1024"
}';

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

content = content(response, "text", encoding = "UTF-8")
content |> fromJSON()
$created
[1] 1739873805

$data
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       url
1 https://oaidalleapiprodscus.blob.core.windows.net/private/org-ZNOJ52bwkaITA98ta51mnxPY/user-lGnbjlc7o2MKy3tKztNgR2Qc/img-vIJm3RQInWWKL7ORFxg5bG6J.png?st=2025-02-18T09%3A16%3A44Z&se=2025-02-18T11%3A16%3A44Z&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=2025-02-17T16%3A50%3A07Z&ske=2025-02-18T16%3A50%3A07Z&sks=b&skv=2024-08-04&sig=pnTLPWMhdGR1wkAfau9FSulTKSaygUCTbhhZshoaWpQ%3D
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              revised_prompt
1 Vivid hues of orange, pink, and purple fill the sky, setting an enchanting backdrop for the day's end. These colors are reflected in a serene, undulating pattern on the glossy surface of a calm lake in the foreground. In the middle distance, a range of snow-capped mountains stretches across the horizontal plane, their peaks appearing as sharp, silhouetted triangles against the dramatic skyscape. The pure white snow on the mountains contrasting with the darkening twilight sky, all bathed in the diminishing warm glow of the sunset, creates a breathtaking panorama of natural beauty.

获取图片。

# 获取生成的图像 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

17.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))

content(res, 'text', encoding = "UTF-8") |> fromJSON()
$error
$error$message
[1] "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]"

$error$type
[1] "chatanywhere_error"

$error$param
NULL

$error$code
[1] "500 INTERNAL_SERVER_ERROR"

17.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))
}

17.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"}

17.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 7
 $ id                : chr "chatcmpl-89DL5Y5ZpqhtEco6nQIrwEDEeLCWq"
 $ 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\"这个单词中有3个字母\"e\"。"
  ..$ logprobs     : logi NA
  ..$ finish_reason: chr "stop"
 $ created           : int 1739873840
 $ model             : chr "claude-3-5-sonnet-20240620"
 $ object            : chr "chat.completion"
 $ usage             :List of 5
  ..$ prompt_tokens            : int 30
  ..$ completion_tokens        : int 20
  ..$ total_tokens             : int 50
  ..$ completion_tokens_details: Named list()
  ..$ prompt_tokens_details    : Named list()
 $ system_fingerprint: NULL

17.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."}

17.11 总结

因为特殊原因,在国内不能直接访问到包括 OpenAI、Claude 等在内的大模型服务。

ChatAnyWhere 提供了一个替代方案,可以让你在国内访问这些大模型服务。

17.12 参考文献