接下來一步一步實現(xiàn):

OpenAI 對接 LangChain

為了統(tǒng)一使用體驗,我們后端使用 LangChain 來對接,先不用 OpenAI 的原生接口,稍微復(fù)雜一點, 但是也沒復(fù)雜多少。

安裝 LangChain

首先安裝 LangChain:

pip install langchain

LangChain + OpenAI + FastAPI

增加接口,使用 LangChain 的?ChatOpenAI來實現(xiàn)問答:

@app.get("/chat/openai")
def ask(prompt: str = Query(..., max_length=40)):
from langchain.schema import AIMessage, HumanMessage, SystemMessage
from langchain.chat_models import ChatOpenAI
chat = ChatOpenAI()
messages = [
SystemMessage(content="簡單回答,使用中文"),
HumanMessage(content=prompt)
]
return TextMessage(chat(messages))

PostMan 測試

用 PostMan 測試下,效果很好:

自定義實現(xiàn) Claude 2 LangChain 對接

Claude API

我們使用開源的?claude-api?來模擬調(diào)用 Claude 2 的 Web 接口。

先安裝:

pip install claude-api

https://github.com/KoushikNavuluri/Claude-API

獲取 Cookie,

把 Cookie 存儲到 環(huán)境變量里面,后面用。

測試 Claude-API

我們編寫?claude.py?來測試下接口:

from claude_api import Client
import os

cookie = os.environ.get('CLAUDE_COOKIE')
claude_api = Client(cookie)

conversation_id = claude_api.create_new_chat()['uuid']

def chat(prompt):
response = claude_api.send_message(prompt, conversation_id)
print(response)
return response

if __name__ == '__main__':
chat('幫我根據(jù)顏色 # 389e0d 生成一組顏色,只返回 json')

接口連接成功,得到如下輸出:

實現(xiàn) LangChain ChatModel 接口

接下來我們參考?ChatOpenAI?實現(xiàn)?ChatClaude。

先安裝 pydantic, 代碼里面用的到:

pip install pydantic

首先引入需要的包:

from pydantic import Field, root_validator

from langchain.schema.language_model import BaseLanguageModel
from langchain.utils import (
get_from_dict_or_env,
)

from typing import Any, AsyncIterator, Dict, Iterator, List, Optional

from langchain.callbacks.manager import (
CallbackManagerForLLMRun,
)
from langchain.chat_models.base import BaseChatModel
from langchain.schema import (
ChatGeneration,
ChatResult,
)
from langchain.schema.messages import (
AIMessage,
BaseMessage,
ChatMessage,
HumanMessage,
SystemMessage,
)

然后實現(xiàn)基礎(chǔ)類?_ClaudeCommon

class _ClaudeCommon(BaseLanguageModel):
HUMAN_PROMPT: Optional[str] = ''
AI_PROMPT: Optional[str] = '簡單回答'

@property
def lc_secrets(self) -> Dict[str, str]:
return {"claude_cookie": "CLAUDE_COOKIE"}

@property
def lc_serializable(self) -> bool:
return True

@root_validator()
def validate_environment(cls, values: Dict) -> Dict:
values["claude_cookie"] = get_from_dict_or_env(values, "claude_cookie", "CLAUDE_COOKIE")
values["conversation_id"] = get_from_dict_or_env(values, "conversation_id", "CONVERSATION_ID")

try:
from claude_api import Client
claude_api = Client(values["claude_cookie"])
values["client"] = claude_api
except ImportError:
raise ImportError(
"Could not import ChatClaude python package. "
)
return values

實現(xiàn)?ChatClaude?類:

class ChatClaude(BaseChatModel, _ClaudeCommon):
@property
def _llm_type(self) -> str:
"""Return type of chat model."""
return "claude-chat"

def _convert_messages_to_text(self, messages: List[BaseMessage]) -> str:
return "".join(
self._convert_one_message_to_text(message) for message in messages
)

def _convert_messages_to_prompt(self, messages: List[BaseMessage]) -> str:
messages = messages.copy() # don't mutate the original list
if not isinstance(messages[-1], AIMessage):
messages.append(AIMessage(content=""))
text = self._convert_messages_to_text(messages)
return (
text.rstrip()
) # trim off the trailing ' ' that might come from the "Assistant: "

def _generate(
self,
messages: List[BaseMessage],
stop: Optional[List[str]] = None,
run_manager: Optional[CallbackManagerForLLMRun] = None,
**kwargs: Any,
) -> ChatResult:
prompt = self._convert_messages_to_prompt(messages)
completion = self.client.send_message(prompt, self.conversation_id)
print(completion)
message = AIMessage(content=completion)
return ChatResult(generations=[ChatGeneration(message=message)])

Claude2 + LangChain + FastAPI

增加 Claude 的接口如下:

@app.get("/chat/claude")
def ask(prompt: str = Query(..., max_length=40)):
from langchain.schema import AIMessage, HumanMessage, SystemMessage
from chat_models import ChatClaude
chat = ChatClaude()
messages = [
SystemMessage(content="簡單回答,使用中文"),
HumanMessage(content=prompt)
]
return TextMessage(chat(messages))

使用 PostMan 測試

使用下面的地址測試:

http://127.0.0.1:8000/chat/claude?prompt=中國的首都是哪里

結(jié)果完美。

前端

后端好了,那我們來改造后前端。

當(dāng)然昨天的 OpenAI 成果是還要留著,我們增加一個按鈕來切換 OpenAI 和 Claude 2 的使用。

添加 LLM 選擇按鈕

先增加兩個按鈕,用來切換 Claude 和 OpenAI,

<div class="div">
<button class="button" onclick="claude('OpenAI')">OpenAI</button>
<button class="button" onclick="claude('Claude')">Claude</button>
</div>

如下:

然后修改下樣式,稍微好看點兒:

.div {
position: fixed;
top: 10px;
right: 40px;
z-index: 9999;
}

.button {
background-image: linear-gradient(135deg, #42e695, #3bb2b8);
border: 0;
color: white;
width: 100px;
height: 40px;
display: block;
margin-bottom: 10px;
border-radius: 20px;
font-weight: 200;
}

.button:last-child {
background-image: linear-gradient(135deg, #f97794, #623aa2);
}

定義切換函數(shù)邏輯

由于 ChatUI 的文檔和 API 不全,我們簡單點,直接用?localStorage?+?reload?來實現(xiàn):

function claude(llm) {
localStorage.setItem('llm', llm)
window.location.reload()
}

修改?setup.js,定義相關(guān)變量給后面用:

const llm = localStorage.getItem('llm') || 'OpenAI'
const url = llm === 'OpenAI' ? 'http://localhost:8000/chat/openai/' : 'http://localhost:8000/chat/claude/'
const welcome1 = '小翼 已鏈接 ' + llm
const welcome2 = 我是小翼的 ${llm} 分身,請問有什么可以幫您?

然后刷新頁面看看效果,點擊 Claude 成功切換,:

本文章轉(zhuǎn)載微信公眾號@數(shù)翼

上一篇:

ChatGPT API接口編程基礎(chǔ)與使用技巧

下一篇:

大模型實戰(zhàn)(二):全民AI?關(guān)于如何在本地私有化部署基于大模型的 AI 應(yīng)用開發(fā)平臺Dify,并集成Xinference大模型
#你可能也喜歡這些API文章!

我們有何不同?

API服務(wù)商零注冊

多API并行試用

數(shù)據(jù)驅(qū)動選型,提升決策效率

查看全部API→
??

熱門場景實測,選對API

#AI文本生成大模型API

對比大模型API的內(nèi)容創(chuàng)意新穎性、情感共鳴力、商業(yè)轉(zhuǎn)化潛力

25個渠道
一鍵對比試用API 限時免費

#AI深度推理大模型API

對比大模型API的邏輯推理準(zhǔn)確性、分析深度、可視化建議合理性

10個渠道
一鍵對比試用API 限時免費