模型(Models)

LangChain的一個(gè)核心價(jià)值就是它提供了標(biāo)準(zhǔn)的模型接口;然后我們可以自由的切換不同的模型,當(dāng)前主要有兩種類型的模型,但是考慮到使用場景,對(duì)我們一般用戶來說就是使用一種模型即文本生成模型。

說到模型,大家就理解模型就是ChatGPT就可以。單純的模型只能生成文本內(nèi)容。

用于文本生成,文字作為輸入,輸出也是文字。

1. 普通LLM:接收文本字符串作為輸入,并返回文本字符串作為輸出。2. 聊天模型:將聊天消息列表作為輸入,并返回一個(gè)聊天消息。代碼案例:

from langchain.schema import HumanMessage
from langchain.llms import OpenAI
from langchain.chat_models import ChatOpenAI
llm = OpenAI()
chat_model = ChatOpenAI()
print(llm("say hi!"))
print(chat_model.predict("say hi!"))

把文字轉(zhuǎn)換為浮點(diǎn)數(shù)形式的描述:

這些模型接收文本作為輸入并返回一組浮點(diǎn)數(shù)。這些浮點(diǎn)數(shù)通常用于表示文本的語義信息,以便進(jìn)行文本相似性計(jì)算、聚類分析等任務(wù)。文本嵌入模型可以幫助開發(fā)者在文本之間建立更豐富的聯(lián)系,提高基于大型語言模型的應(yīng)用的性能。

from langchain.embeddings import OpenAIEmbeddings
embeddings = OpenAIEmbeddings()
text = "This is a test document."
query_result = embeddings.embed_query(text)
doc_result = embeddings.embed_documents([text])
print(doc_result)

提示詞(Prompts)

提示詞是我們與模型交互的方式,或者是模型的輸入,通過提示詞可以讓模型返回我們期望的內(nèi)容,比如讓模型按照一定的格式返回?cái)?shù)據(jù)給我們。LangChain提供了一些工具,可以方便我們更容易的構(gòu)建出我們想要的提示詞,主要工具如下:了解這些工具都是更方便的讓我們構(gòu)造提示詞就行了。

語言模型提示詞模板PromptTemplates,提示模板可以讓我們重復(fù)的生成提示,復(fù)用我們的提示。它包含一個(gè)文本字符串(“模板”),從用戶那里獲取一組參數(shù)并生成提示,包含:

1. 對(duì)語言模型的說明,應(yīng)該扮演什么角色。

2. 一組少量示例,以幫助LLM生成更好的響應(yīng)。3. 具體的問題。代碼案例:

from langchain import PromptTemplate

template = """
I want you to act as a naming consultant for new companies.
What is a good name for a company that makes {product}?
"""

prompt = PromptTemplate(
input_variables=["product"],
template=template,
)
prompt.format(product="colorful socks")
# -> I want you to act as a naming consultant for new companies.
# -> What is a good name for a company that makes colorful socks?

聊天模型提示詞模板ChatPrompt Templates,ChatModels接受聊天消息列表作為輸入。列表一般是不同的提示,并且每個(gè)列表消息一般都會(huì)有一個(gè)角色。

from langchain.prompts import (
ChatPromptTemplate,
PromptTemplate,
SystemMessagePromptTemplate,
AIMessagePromptTemplate,
HumanMessagePromptTemplate,
)
from langchain.schema import (
AIMessage,
HumanMessage,
SystemMessage
)
template="You are a helpful assistant that translates {input_language} to {output_language}."
system_message_prompt = SystemMessagePromptTemplate.from_template(template)
human_template="{text}"
human_message_prompt = HumanMessagePromptTemplate.from_template(human_template)

chat_prompt = ChatPromptTemplate.from_messages([system_message_prompt, human_message_prompt])

# get a chat completion from the formatted messages
print(chat_prompt.format_prompt(input_language="English", output_language="French", text="I love programming.").to_messages())

示例選擇器Example Selectors,如果有多個(gè)案例的時(shí)候,使用ExampleSelectors選擇一個(gè)案例讓提示詞使用:1. 自定義的案例選擇器。2. 基于長度的案例選擇器,輸入長的時(shí)候按理會(huì)少一點(diǎn),輸入多的時(shí)候,案例會(huì)多一些。3. 相關(guān)性選擇器,選擇一個(gè)和輸入最相關(guān)的案例。

from langchain.prompts.example_selector.base import BaseExampleSelector
from typing import Dict, List
import numpy as np

class CustomExampleSelector(BaseExampleSelector):

def __init__(self, examples: List[Dict[str, str]]):
self.examples = examples

def add_example(self, example: Dict[str, str]) -> None:
"""Add new example to store for a key."""
self.examples.append(example)

def select_examples(self, input_variables: Dict[str, str]) -> List[dict]:
"""Select which examples to use based on the inputs."""
return np.random.choice(self.examples, size=2, replace=False)

examples = [
{"foo": "1"},
{"foo": "2"},
{"foo": "3"}
]

# Initialize example selector.
example_selector = CustomExampleSelector(examples)
# Select examples
print(example_selector.select_examples({"foo": "foo"}))
# -> array([{'foo': '2'}, {'foo': '3'}], dtype=object)
# Add new example to the set of examples
example_selector.add_example({"foo": "4"})
print(example_selector.examples)
# -> [{'foo': '1'}, {'foo': '2'}, {'foo': '3'}, {'foo': '4'}]
# Select examples
print(example_selector.select_examples({"foo": "foo"}))
# -> array([{'foo': '1'}, {'foo': '4'}], dtype=object)

輸出解析器OutputParsers,可以讓LLM輸出更加結(jié)構(gòu)化的信息:

1. 指示模型如何格式化輸出:get_format_instructions2. 輸出解析為所需的格式:parse(str)主要的Parsers:1. CommaSeparatedListOutputParser,讓LLM按照逗號(hào)分隔的形式返回。[‘Vanilla’,  ‘Chocolate’,  ‘Strawberry’,  ‘Mint Chocolate Chip’,  ‘Cookies and Cream’]2. StructuredOutputParser 無需定義對(duì)象,直接生成結(jié)構(gòu)化的內(nèi)容。和PydanticOutputParser比較像,但是不用定義對(duì)象。

3. PydanticOutputParser定義一個(gè)對(duì)象模型,讓LLM按照這個(gè)模型返回?cái)?shù)據(jù)。

可以看到我們定義了Joke類,然后PydanticOutputParser可以讓LLM按照我們定義對(duì)象的格式返回?cái)?shù)據(jù)給我們。

from langchain.prompts import PromptTemplate, ChatPromptTemplate, HumanMessagePromptTemplate
from langchain.llms import OpenAI
from langchain.chat_models import ChatOpenAI

from langchain.output_parsers import PydanticOutputParser
from pydantic import BaseModel, Field, validator
from typing import List
model_name = 'text-davinci-003'
temperature = 0.0
model = OpenAI(model_name=model_name, temperature=temperature)

# Define your desired data structure.
class Joke(BaseModel):
setup: str = Field(description="question to set up a joke")
punchline: str = Field(description="answer to resolve the joke")

# You can add custom validation logic easily with Pydantic.
@validator('setup')
def question_ends_with_question_mark(cls, field):
if field[-1] != '?':
raise ValueError("Badly formed question!")
return field

parser = PydanticOutputParser(pydantic_object=Joke)
prompt = PromptTemplate(
template="Answer the user query.\n{format_instructions}\n{query}\n",
input_variables=["query"],
partial_variables={"format_instructions": parser.get_format_instructions()}
)
joke_query = "Tell me a joke."
_input = prompt.format_prompt(query=joke_query)
output = model(_input.to_string())
print(parser.get_format_instructions())
print(output)
print(parser.parse(output))

索引(Indexs)

索引可以讓文檔結(jié)構(gòu)化,從而LLM可以直接更好的和文檔交互;比如用于答疑,知識(shí)庫等,LLM先從文檔中獲取答案。LangChain在索引這塊也提供了許多有用的函數(shù)和工具,方便我們從外部加載與檢索不同的文檔數(shù)據(jù)。

在數(shù)據(jù)索引這塊,LangChain提供的主要工具:1. Document Loaders:從不同的數(shù)據(jù)源加載文檔,當(dāng)使用loader加載器讀取到數(shù)據(jù)源后,數(shù)據(jù)源需要轉(zhuǎn)換成 Document 對(duì)象后,后續(xù)才能進(jìn)行使用。2. Text Splitters:實(shí)現(xiàn)文本分割,我們每次不管是做把文本當(dāng)作 prompt 發(fā)給 openai api ,還是還是使用 openai api embedding 功能都是有字符限制的。比如我們將一份300頁的 pdf 發(fā)給 openai api,讓他進(jìn)行總結(jié),他肯定會(huì)報(bào)超過最大 Token 錯(cuò)。所以這里就需要使用文本分割器去分割我們 loader 進(jìn)來的 Document。3. VectorStores:把文檔存儲(chǔ)為向量結(jié)構(gòu),因?yàn)閿?shù)據(jù)相關(guān)性搜索其實(shí)是向量運(yùn)算。所以,不管我們是使用 openai api embedding 功能還是直接通過向量數(shù)據(jù)庫直接查詢,都需要將我們的加載進(jìn)來的數(shù)據(jù) Document 進(jìn)行向量化,才能進(jìn)行向量運(yùn)算搜索。轉(zhuǎn)換成向量也很簡單,只需要我們把數(shù)據(jù)存儲(chǔ)到對(duì)應(yīng)的向量數(shù)據(jù)庫中即可完成向量的轉(zhuǎn)換。4. Retrievers:用于檢索文檔的數(shù)據(jù)。

圖中的FAISS是一種向量存儲(chǔ)的服務(wù);

給一個(gè)案例,了解下不同工具的用法:1. 首先加載文檔;2. 然后分隔文檔為不同區(qū)塊;3. 然后轉(zhuǎn)換為向量存儲(chǔ);4. 將向量存儲(chǔ)轉(zhuǎn)換為檢索器,交給LangChain,用于問答;

import os
from langchain.chains import RetrievalQA
from langchain.document_loaders import TextLoader
from langchain.embeddings import OpenAIEmbeddings
from langchain.indexes import VectorstoreIndexCreator
from langchain.text_splitter import CharacterTextSplitter
from langchain.vectorstores import Chroma
from langchain.llms import OpenAI

# 設(shè)置代理
os.environ['HTTP_PROXY'] = 'socks5h://127.0.0.1:13659'
os.environ['HTTPS_PROXY'] = 'socks5h://127.0.0.1:13659'

# 創(chuàng)建文本加載器
loader = TextLoader('/Users/aihe/Downloads/demo.txt', encoding='utf8')

# 加載文檔
documents = loader.load()

# 文本分塊
text_splitter = CharacterTextSplitter(chunk_size=1000, chunk_overlap=0)
texts = text_splitter.split_documents(documents)

# 計(jì)算嵌入向量
embeddings = OpenAIEmbeddings()

# 創(chuàng)建向量庫
db = Chroma.from_documents(texts, embeddings)

# 將向量庫轉(zhuǎn)換為檢索器
retriever = db.as_retriever()

# 創(chuàng)建檢索問答系統(tǒng)
qa = RetrievalQA.from_chain_type(llm=OpenAI(), chain_type="stuff", retriever=retriever)

# 運(yùn)行問題答案檢索
query = "如何申請(qǐng)租戶?"
print(qa.run(query))

print(qa.run("能否說明下你可以提供的功能?"))

存儲(chǔ)(Memory)

默認(rèn)情況下Agent和Chain都是無狀態(tài)的,也就是用完之后不知道上次的對(duì)話內(nèi)容是什么。每次的query都是獨(dú)立的。

但是在有些應(yīng)用中,記住上一次的會(huì)話內(nèi)容是比較重要的,比如聊天,LangChain對(duì)于也提供了一些相關(guān)的工具類。

from langchain import ConversationChain, OpenAI
from langchain.memory import ConversationBufferMemory

memory = ConversationBufferMemory()
memory.chat_memory.add_user_message("你好!")
memory.chat_memory.add_ai_message("你好嗎?")
llm = OpenAI(temperature=0)
chain = ConversationChain(llm=llm,
verbose=True,
memory=memory)
chain.predict(input="最近怎么樣!")
print(chain.predict(input="感覺很不錯(cuò),剛和AI做了場對(duì)話."))

鏈(Chains)

鏈可以讓我們把多個(gè)組件組合成一個(gè)應(yīng)用,比如我們創(chuàng)建一個(gè)鏈,這個(gè)鏈可以接受用戶的輸入,然后通過PromptTemplate格式化用戶的輸入為提示詞,然后把這個(gè)提示詞輸入給LLM。我們也可以把一些鏈組合在一起,構(gòu)建更復(fù)雜的鏈。

一個(gè)簡單的案例:

# 引入所需模塊和類
from langchain.chains import LLMChain
from langchain.chat_models import ChatOpenAI
from langchain import PromptTemplate
from langchain.prompts.chat import (
ChatPromptTemplate, # 引入對(duì)話模板類
HumanMessagePromptTemplate, # 引入人類消息模板類
)

# 創(chuàng)建人類消息模板類
human_message_prompt = HumanMessagePromptTemplate(
prompt=PromptTemplate(
template="給我一個(gè)制作{product}的好公司名字?", # 輸入模板,其中product為占位符
input_variables=["product"], # 指定輸入變量為product
)
)

# 創(chuàng)建對(duì)話模板類
chat_prompt_template = ChatPromptTemplate.from_messages([human_message_prompt])

# 創(chuàng)建OpenAI聊天模型對(duì)象
chat = ChatOpenAI(temperature=0.9)

# 創(chuàng)建LLMChain對(duì)象,將聊天模型和對(duì)話模板傳入
chain = LLMChain(llm=chat, prompt=chat_prompt_template)

# 運(yùn)行LLMChain對(duì)象,并輸出結(jié)果
print(chain.run("襪子"))

代理(Agents)

代理是使用LLM作為思考工具,決定當(dāng)前要做什么。我們會(huì)給代理一系列的工具,代理根據(jù)我們的輸入判斷用哪些工具可以完成這個(gè)目標(biāo),然后不斷的運(yùn)行工具,來完成目標(biāo)。代理可以看做是增強(qiáng)版的Chain,不僅綁定模板、LLM,還可以給代理添加一些工具。

Agent是一個(gè)智能代理,它負(fù)責(zé)根據(jù)用戶輸入和應(yīng)用場景,在一系列可用工具中選擇合適的工具進(jìn)行操作。Agent可以根據(jù)任務(wù)的復(fù)雜性,采用不同的策略來決定如何執(zhí)行操作。

有兩種類型的Agent:1. 動(dòng)作代理(Action Agents):這種代理一次執(zhí)行一個(gè)動(dòng)作,然后根據(jù)結(jié)果決定下一步的操作。

2. 計(jì)劃-執(zhí)行代理(Plan-and-Execute Agents):這種代理首先決定一系列要執(zhí)行的操作,然后根據(jù)上面判斷的列表逐個(gè)執(zhí)行這些操作。對(duì)于簡單的任務(wù),動(dòng)作代理更為常見且易于實(shí)現(xiàn)。對(duì)于更復(fù)雜或長期運(yùn)行的任務(wù),計(jì)劃-執(zhí)行代理的初始規(guī)劃步驟有助于維持長期目標(biāo)并保持關(guān)注。但這會(huì)以更多調(diào)用和較高延遲為代價(jià)。這兩種代理并非互斥,可以讓動(dòng)作代理負(fù)責(zé)執(zhí)行計(jì)劃-執(zhí)行代理的計(jì)劃。

Agent內(nèi)部涉及的核心概念如下:
1. 代理(Agent):這是應(yīng)用程序主要邏輯。代理暴露一個(gè)接口,接受用戶輸入和代理已執(zhí)行的操作列表,并返回AgentAction或AgentFinish。

2. 工具(Tools):這是代理可以采取的動(dòng)作。比如發(fā)起HTTP請(qǐng)求,發(fā)郵件,執(zhí)行命令。

3. 工具包(Toolkits):這些是為特定用例設(shè)計(jì)的一組工具。例如,為了讓代理以最佳方式與SQL數(shù)據(jù)庫交互,它可能需要一個(gè)執(zhí)行查詢的工具和另一個(gè)查看表格的工具。可以看做是工具的集合。

4. 代理執(zhí)行器(Agent Executor):這將代理與一系列工具包裝在一起。它負(fù)責(zé)迭代運(yùn)行代理,直到滿足停止條件。

代理的執(zhí)行流程:

一個(gè)案例:

# 引入所需模塊和類
from langchain.agents import load_tools # 引入加載工具函數(shù)
from langchain.agents import initialize_agent # 引入初始化代理函數(shù)
from langchain.agents import AgentType # 引入代理類型類
from langchain.llms import OpenAI # 引入OpenAI語言模型類
import os # 引入os模塊

# 創(chuàng)建OpenAI語言模型對(duì)象,設(shè)定temperature為0,即關(guān)閉隨機(jī)性
llm = OpenAI(temperature=0)

# 加載所需工具,包括serpapi和llm-math
tools = load_tools(["serpapi", "llm-math"], llm=llm)

# 初始化代理對(duì)象,設(shè)定代理類型為ZERO_SHOT_REACT_DESCRIPTION,輸出詳細(xì)信息
agent = initialize_agent(tools, llm, agent=AgentType.ZERO_SHOT_REACT_DESCRIPTION, verbose=True)

# 運(yùn)行代理對(duì)象,向其提問特朗普的年齡和年齡除以2的結(jié)果
agent.run("特朗普今年多少歲? 他的年齡除以2是多少?")

上述代碼中關(guān)于Agent有個(gè)初始化的階段,agent=AgentType.ZERO_SHOT_REACT_DESCRIPTION,代理類型決定了代理如何使用工具、處理輸入以及與用戶進(jìn)行交互。從而為用戶提供有針對(duì)性的服務(wù)。其中可以選擇的類型如下:

initialize_agent(tools, llm, agent=AgentType.ZERO_SHOT_REACT_DESCRIPTION, verbose=True)

1. zero-shot-react-description:該代理使用ReAct框架僅根據(jù)工具的描述來確定要使用哪個(gè)工具,可以提供任意數(shù)量的工具。要求為每個(gè)工具提供一個(gè)描述。

2. react-docstore:該代理使用ReAct框架與文檔存儲(chǔ)(docstore)進(jìn)行交互。必須提供兩個(gè)工具:一個(gè)搜索工具和一個(gè)查找工具(它們必須確切地命名為Search和Lookup)。搜索工具應(yīng)該用于搜索文檔,而查找工具應(yīng)該在最近找到的文檔中查找術(shù)語。該代理等同于原始的ReAct論文,特別是維基百科的示例。

3. self-ask-with-search:該代理使用一個(gè)名為Intermediate Answer的單一工具。這個(gè)工具應(yīng)該能夠查找問題的事實(shí)性答案。這個(gè)代理等同于原始的自問自答(self-ask)與搜索論文,其中提供了作為工具的谷歌搜索API。

4. conversational-react-description該代理旨在用于對(duì)話設(shè)置中。提示讓代理在對(duì)話中變得有幫助。它使用ReAct框架來決定使用哪個(gè)工具,并使用內(nèi)存來記住之前的對(duì)話互動(dòng)。5. structured-chat-zero-shot-react-description:  在對(duì)話中可以使用任意的工具,并且能夠記住對(duì)話的上下文。

官方已經(jīng)默認(rèn)提供了一系列的工具箱,發(fā)Gmail郵件,數(shù)據(jù)庫查詢,JSON處理等;還有一些單個(gè)的工具列表,都可以在文檔中看到:

https://python.langchain.com/en/latest/modules/agents/tools/getting_started.html

我們通過一個(gè)自定義的工具,了解下工具怎么用,因?yàn)楹竺嬖偈褂肔angChain的時(shí)候我們做的也就是不斷的自定義工具。編寫工具的時(shí)候,要準(zhǔn)備:

1. 名稱。

2. 工具描述:說明你的工具是做什么的?

3. 參數(shù)結(jié)構(gòu):當(dāng)前工具需要的入?yún)⑹鞘裁唇Y(jié)構(gòu)?

LangChain應(yīng)用案例

假設(shè)我們需要構(gòu)建一個(gè)基于LLM的問答系統(tǒng),該系統(tǒng)需要從指定的數(shù)據(jù)源中提取信息以回答用戶的問題。我們可以使用LangChain中的數(shù)據(jù)增強(qiáng)生成功能與外部數(shù)據(jù)源進(jìn)行交互,獲取所需的數(shù)據(jù)。然后,將數(shù)據(jù)輸入到LLM中,生成回答。記憶功能可以幫助我們?cè)诙啻握{(diào)用之間保持相關(guān)狀態(tài),從而提高問答系統(tǒng)的性能。此外,我們還可以使用智能代理功能實(shí)現(xiàn)系統(tǒng)的自動(dòng)優(yōu)化。最后,通過LangChain提供的評(píng)估提示和鏈實(shí)現(xiàn),我們可以對(duì)問答系統(tǒng)的性能進(jìn)行評(píng)估和優(yōu)化。

LangChain生成圖片

實(shí)現(xiàn)了一個(gè)基于語言模型的文本生成圖片工具,調(diào)用不同的工具函數(shù)來最終生成圖片。主要提供了以下幾個(gè)工具:

1. random_poem:隨機(jī)返回中文的詩詞。

2. prompt_generate:根據(jù)中文提示詞生成對(duì)應(yīng)的英文提示詞。3. generate_image:根據(jù)英文提示詞生成對(duì)應(yīng)的圖片。

import base64
import json
import os
from io import BytesIO

import requests
from PIL import Image
from pydantic import BaseModel, Field

from langchain.agents import AgentType, initialize_agent, load_tools
from langchain.chat_models import ChatOpenAI
from langchain.llms import OpenAI
from langchain.tools import BaseTool, StructuredTool, Tool, tool
from langchain import LLMMathChain, SerpAPIWrapper

def generate_image(prompt: str) -> str:
"""
根據(jù)提示詞生成對(duì)應(yīng)的圖片

Args:
prompt (str): 英文提示詞

Returns:
str: 圖片的路徑
"""
url = "http://127.0.0.1:7860/sdapi/v1/txt2img"
headers = {
"accept": "application/json",
"Content-Type": "application/json"
}
data = {
"prompt": prompt,
"negative_prompt": "(worst quality:2), (low quality:2),disfigured, ugly, old, wrong finger",
"steps": 20,
"sampler_index": "Euler a",
"sd_model_checkpoint": "cheeseDaddys_35.safetensors [98084dd1db]",
# "sd_model_checkpoint": "anything-v3-fp16-pruned.safetensors [d1facd9a2b]",
"batch_size": 1,
"restore_faces": True
}

response = requests.post(url, headers=headers, data=json.dumps(data))

if response.status_code == 200:
response_data = response.json()
images = response_data['images']

for index, image_data in enumerate(images):
img_data = base64.b64decode(image_data)
img = Image.open(BytesIO(img_data))
file_name = f"image_{index}.png"
file_path = os.path.join(os.getcwd(), file_name)
img.save(file_path)
print(f"Generated image saved at {file_path}")
return file_path
else:
print(f"Request failed with status code {response.status_code}")

def random_poem(arg: str) -> str:
"""
隨機(jī)返回中文的詩詞

Returns:
str: 隨機(jī)的中文詩詞
"""
llm = OpenAI(temperature=0.9)
text = """
能否幫我從中國的詩詞數(shù)據(jù)庫中隨機(jī)挑選一首詩給我,希望是有風(fēng)景,有畫面的詩:
比如:山重水復(fù)疑無路,柳暗花明又一村。
"""
return llm(text)

def prompt_generate(idea: str) -> str:
"""
生成圖片需要對(duì)應(yīng)的英文提示詞

Args:
idea (str): 中文提示詞

Returns:
str: 英文提示詞
"""
llm = OpenAI(temperature=0, max_tokens=2048)
res = llm(f"""
Stable Diffusion is an AI art generation model similar to DALLE-2.
Below is a list of prompts that can be used to generate images with Stable Diffusion:

- portait of a homer simpson archer shooting arrow at forest monster, front game card, drark, marvel comics, dark, intricate, highly detailed, smooth, artstation, digital illustration by ruan jia and mandy jurgens and artgerm and wayne barlowe and greg rutkowski and zdislav beksinski
- pirate, concept art, deep focus, fantasy, intricate, highly detailed, digital painting, artstation, matte, sharp focus, illustration, art by magali villeneuve, chippy, ryan yee, rk post, clint cearley, daniel ljunggren, zoltan boros, gabor szikszai, howard lyon, steve argyle, winona nelson
- ghost inside a hunted room, art by lois van baarle and loish and ross tran and rossdraws and sam yang and samdoesarts and artgerm, digital art, highly detailed, intricate, sharp focus, Trending on Artstation HQ, deviantart, unreal engine 5, 4K UHD image
- red dead redemption 2, cinematic view, epic sky, detailed, concept art, low angle, high detail, warm lighting, volumetric, godrays, vivid, beautiful, trending on artstation, by jordan grimmer, huge scene, grass, art greg rutkowski
- a fantasy style portrait painting of rachel lane / alison brie hybrid in the style of francois boucher oil painting unreal 5 daz. rpg portrait, extremely detailed artgerm greg rutkowski alphonse mucha greg hildebrandt tim hildebrandt
- athena, greek goddess, claudia black, art by artgerm and greg rutkowski and magali villeneuve, bronze greek armor, owl crown, d & d, fantasy, intricate, portrait, highly detailed, headshot, digital painting, trending on artstation, concept art, sharp focus, illustration
- closeup portrait shot of a large strong female biomechanic woman in a scenic scifi environment, intricate, elegant, highly detailed, centered, digital painting, artstation, concept art, smooth, sharp focus, warframe, illustration, thomas kinkade, tomasz alen kopera, peter mohrbacher, donato giancola, leyendecker, boris vallejo
- ultra realistic illustration of steve urkle as the hulk, intricate, elegant, highly detailed, digital painting, artstation, concept art, smooth, sharp focus, illustration, art by artgerm and greg rutkowski and alphonse mucha

I want you to write me a list of detailed prompts exactly about the idea written after IDEA. Follow the structure of the example prompts. This means a very short description of the scene, followed by modifiers divided by commas to alter the mood, style, lighting, and more.

IDEA: {idea}""")
return res

class PromptGenerateInput(BaseModel):
"""
生成英文提示詞所需的輸入模型類
"""
idea: str = Field()

class GenerateImageInput(BaseModel):
"""
生成圖片所需的輸入模型類
"""
prompt: str = Field(description="英文提示詞")

tools = [
Tool.from_function(
func=random_poem,
name="詩歌獲取",
description="隨機(jī)返回中文的詩詞"
),
Tool.from_function(
func=prompt_generate,
name="提示詞生成",
description="生成圖片需要對(duì)應(yīng)的英文提示詞,當(dāng)前工具可以將輸入轉(zhuǎn)換為英文提示詞,以便方便生成",
args_schema=PromptGenerateInput
),
Tool.from_function(
func=generate_image,
name="圖片生成",
description="根據(jù)提示詞生成對(duì)應(yīng)的圖片,提示詞需要是英文的,返回是圖片的路徑",
args_schema=GenerateImageInput
),
]

def main():
"""
主函數(shù),初始化代理并執(zhí)行對(duì)話
"""
llm = OpenAI(temperature=0)
agent = initialize_agent(tools, llm, agent=AgentType.ZERO_SHOT_REACT_DESCRIPTION, verbose=True)
agent.run("幫我生成一張?jiān)娫~的圖片?")

if __name__ == '__main__':
main()

LangChain做答疑

參考上面的索引部分:

import os
from langchain.chains import RetrievalQA
from langchain.document_loaders import TextLoader
from langchain.embeddings import OpenAIEmbeddings
from langchain.indexes import VectorstoreIndexCreator
from langchain.text_splitter import CharacterTextSplitter
from langchain.vectorstores import Chroma
from langchain.llms import OpenAI

# 設(shè)置代理
os.environ['HTTP_PROXY'] = 'socks5h://127.0.0.1:13659'
os.environ['HTTPS_PROXY'] = 'socks5h://127.0.0.1:13659'

# 創(chuàng)建文本加載器
loader = TextLoader('/Users/aihe/Downloads/demo.txt', encoding='utf8')

# 加載文檔
documents = loader.load()

# 文本分塊
text_splitter = CharacterTextSplitter(chunk_size=1000, chunk_overlap=0)
texts = text_splitter.split_documents(documents)

# 計(jì)算嵌入向量
embeddings = OpenAIEmbeddings()

# 創(chuàng)建向量庫
db = Chroma.from_documents(texts, embeddings)

# 將向量庫轉(zhuǎn)換為檢索器
retriever = db.as_retriever()

# 創(chuàng)建檢索問答系統(tǒng)
qa = RetrievalQA.from_chain_type(llm=OpenAI(), chain_type="stuff", retriever=retriever)

# 運(yùn)行問題答案檢索
query = "如何申請(qǐng)租戶?"
print(qa.run(query))

print(qa.run("能否說明下你可以提供的功能?"))

Langchain輸出結(jié)構(gòu)化JSON數(shù)據(jù)

參考上述概念,提示詞工具中提供了OutputParser可以把我們的對(duì)象轉(zhuǎn)換為提示詞,告訴LLM要返回什么結(jié)構(gòu)的內(nèi)容。

import requests
from langchain.agents import AgentType, initialize_agent
from langchain.chat_models import ChatOpenAI
from langchain.tools import StructuredTool
from pydantic import BaseModel, Field

def post_message(type: str, param: dict) -> str:
"""
當(dāng)需要生成人群、分析畫像、咨詢問題時(shí),使用如下的指示:url 固定為:http://localhost:3001/
如果請(qǐng)求是生成人群,請(qǐng)求的type為crowd; 如果請(qǐng)求是分析畫像,請(qǐng)求的type為analyze; 如果是其他或者答疑,請(qǐng)求的type為question;
請(qǐng)求body的param把用戶指定的條件傳進(jìn)來即可
"""
result = requests.post("http://localhost:3001/", json={"type": type, "param": param})
return f"Status: {result.status_code} - {result.text}"

class PostInput(BaseModel):
# body: dict = Field(description="""格式:{"type":"","param":{}}""")
type: str = Field(description="請(qǐng)求的類型,人群為crowd,畫像為analyze")
param: dict = Field(description="請(qǐng)求的具體描述")

llm = ChatOpenAI(temperature=0)
tools = [
StructuredTool.from_function(post_message)
]
agent = initialize_agent(tools, llm, agent=AgentType.STRUCTURED_CHAT_ZERO_SHOT_REACT_DESCRIPTION, verbose=True)
agent.run("我想生成一個(gè)性別為男并且在180天訪問過淘特的人群?")

LangChain做一款自己的聊天機(jī)器人

原本做聊天機(jī)器人,需要一些前端代碼,但是已經(jīng)有相應(yīng)的開源工具,幫我們把LangChian的各種組件做了可視化,直接拖拽即可,我們直接使用LangFlow;

pip install langflow

然后運(yùn)行命令:

langfow

如果和本地的LangChain有沖突,可以使用Docker運(yùn)行l(wèi)angfow:

FROM python:3.10-slim

RUN apt-get update && apt-get install gcc g++ git make -y
RUN useradd -m -u 1000 user
USER user
ENV HOME=/home/user \
PATH=/home/user/.local/bin:$PATH

WORKDIR $HOME/app

COPY --chown=user . $HOME/app

RUN pip install langflow>==0.0.71 -U --user
CMD ["langflow", "--host", "0.0.0.0", "--port", "7860"]

在界面上配置LangChain的三個(gè)組件:在最右下角是對(duì)應(yīng)的聊天窗口,輸入下openai的key。

開始聊天驗(yàn)證下我們的配置:

全程基本上不用怎么寫代碼,只需要了解LangChain的組件是做什么的,基本上就可以搭出一款簡單的聊天機(jī)器人。

其它的LangChain組件代理、內(nèi)存、數(shù)據(jù)索引也是都可以使用的。

LangChain的未來展望

LangChain為構(gòu)建基于大型語言模型的應(yīng)用提供了一個(gè)強(qiáng)大的框架,將逐步的運(yùn)用到各個(gè)領(lǐng)域中,如:智能客服、文本生成、知識(shí)圖譜構(gòu)建等。隨著更多的工具和資源與LangChain進(jìn)行集成,大語言模型對(duì)人的生產(chǎn)力將會(huì)有更大的提升。

應(yīng)用場景構(gòu)思:

現(xiàn)在有個(gè)平臺(tái)已經(jīng)實(shí)現(xiàn)了大部分:https://zapier.com/l/natural-language-actions。底層為OpenAI模型,使用 zapier 來實(shí)現(xiàn)將萬種工具連接起來。可以在這個(gè)平臺(tái)上配置各種工具,模型會(huì)根據(jù)你的目標(biāo)選擇相應(yīng)的動(dòng)作。工作內(nèi)容自動(dòng)化在不遠(yuǎn)處很快就會(huì)實(shí)現(xiàn)。

總結(jié)

本文介紹了LangChain框架,它能夠?qū)⒋笮驼Z言模型與其他計(jì)算或知識(shí)來源相結(jié)合,從而實(shí)現(xiàn)功能更加強(qiáng)大的應(yīng)用。接著,對(duì)LangChain的關(guān)鍵概念進(jìn)行了詳細(xì)說明,并基于該框架進(jìn)行了一些案例嘗試,旨在幫助讀者更輕松地理解LangChain的工作原理。展望未來,LangChain有望在各個(gè)領(lǐng)域發(fā)揮巨大作用,促進(jìn)我們工作效率的變革。我們正處于AI爆發(fā)的前夜,積極擁抱新技術(shù)將會(huì)帶來完全不同的感覺。

參考資料:
1. Langchain中文入門:https://github.com/liaokongVFX/LangChain-Chinese-Getting-Started-Guide

2. LangChain官方文檔:https://python.langchain.com/en/latest/modules/indexes/getting_started.html

3. LangFlow,LangChain的可視化編排工具:https://github.com/logspace-ai/langflow

文章轉(zhuǎn)自微信公眾號(hào)@阿里云開發(fā)者

上一篇:

阿里云開源AI應(yīng)用開發(fā)框架:Spring AI Alibaba

下一篇:

10分鐘打造企業(yè)微信AI助手
#你可能也喜歡這些API文章!

我們有何不同?

API服務(wù)商零注冊(cè)

多API并行試用

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

查看全部API→
??

熱門場景實(shí)測,選對(duì)API

#AI文本生成大模型API

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

25個(gè)渠道
一鍵對(duì)比試用API 限時(shí)免費(fèi)

#AI深度推理大模型API

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

10個(gè)渠道
一鍵對(duì)比試用API 限時(shí)免費(fèi)