鍵.png)
GraphRAG:基于PolarDB+通義千問api+LangChain的知識圖譜定制實(shí)踐
def _call(
self,
prompt: str,
stop: Optional[List[str]] = None,
run_manager: Optional[CallbackManagerForLLMRun] = None,
**kwargs: Any,
) -> str:
"""Run the LLM on the given prompt and input."""
def _generate(
self,
prompts: List[str],
stop: Optional[List[str]] = None,
run_manager: Optional[CallbackManagerForLLMRun] = None,
**kwargs: Any,
) -> LLMResult:
"""Run the LLM on the given prompt and input."""
Embedding模塊 提供統(tǒng)一的embedding能力接口,與LLM一樣,也提供不同的廠商實(shí)現(xiàn),比如OpenAIEmbeddings,DashScopeEmbeddings。同樣需要集成和實(shí)現(xiàn)Embeddings基類的兩個(gè)方法embed_documents和embed_query。
class Embeddings(ABC):
"""Interface for embedding models."""
@abstractmethod
def embed_documents(self, texts: List[str]) -> List[List[float]]:
"""Embed search docs."""
@abstractmethod
def embed_query(self, text: str) -> List[float]:
VectorStore模塊 向量存儲模塊,用于存儲由Embedding模塊生成的向量和生產(chǎn)向量的數(shù)據(jù),主要作為記憶和檢索模塊向LLM提供服務(wù)。比如AnalytiDB VectorStore模塊。實(shí)現(xiàn)VectorStore模塊主要需要實(shí)現(xiàn)幾個(gè)寫入和查詢接口。
class VectorStore(ABC):
"""Interface for vector store."""
@abstractmethod
def add_texts(
self,
texts: Iterable[str],
metadatas: Optional[List[dict]] = None,
**kwargs: Any,
) -> List[str]:
def search(self, query: str, search_type: str, **kwargs: Any) -> List[Document]:
Chain模塊 用于串聯(lián)上面的這些模塊,使得調(diào)用更加簡單,讓用戶不需要關(guān)心繁瑣的調(diào)用鏈路,在LangChain中已經(jīng)集成了很多chain,最主要的就是LLMChain,在其內(nèi)部根據(jù)不同的場景定義和使用了不同的PromptTemplate來達(dá)到目標(biāo)。
Agents模塊 和chain類似,提供了豐富的agent模版,用于實(shí)現(xiàn)不同的agent,后面會詳細(xì)介紹。
還有一些模塊比如indexes,retrievers等都是上面這些模塊的變種,以及提供一些可調(diào)用的工具類,比如tools等。這里就不再詳細(xì)展開。我們會在后面的案例中講解如何使用這些模塊來構(gòu)建自己的應(yīng)用。
ChatBot是LLM應(yīng)用的一個(gè)比較典型的場景,這個(gè)場景又可以細(xì)分為問答助手(知識庫),智能客服,Copilot等。比較典型的案例是LangChain-chatchat.構(gòu)建ChatBot主要需要以下模塊:
TextSplitter一篇文檔的內(nèi)容往往篇幅較長,由于LLM和Embedding token限制,無法將其全部傳給LLM,因此將需要存儲的文檔按照一定的規(guī)則切分成內(nèi)聚的小塊chunk進(jìn)行存儲。
LLM模塊 用于總結(jié)問題和回答問題。
Embedding模塊 用于生產(chǎn)知識和問題的向量表示。
VectorStore模塊 用于存儲和檢索匹配的本地知識內(nèi)容。
一個(gè)比較清晰的調(diào)用鏈路圖如下(比較經(jīng)典清晰,老圖借用):
首先我們從Google拉取一些問答數(shù)據(jù),然后調(diào)用Dashscope上的Embedding模型進(jìn)行向量化,并寫入AnalyticDB PostgreSQL。
import os
import json
import wget
from langchain.vectorstores.analyticdb import AnalyticDB
CONNECTION_STRING = AnalyticDB.connection_string_from_db_params(
driver=os.environ.get("PG_DRIVER", "psycopg2cffi"),
host=os.environ.get("PG_HOST", "localhost"),
port=int(os.environ.get("PG_PORT", "5432")),
database=os.environ.get("PG_DATABASE", "postgres"),
user=os.environ.get("PG_USER", "postgres"),
password=os.environ.get("PG_PASSWORD", "postgres"),
)
# All the examples come from https://ai.google.com/research/NaturalQuestions
# This is a sample of the training set that we download and extract for some
# further processing.
wget.download("https://storage.googleapis.com/dataset-natural-questions/questions.json")
wget.download("https://storage.googleapis.com/dataset-natural-questions/answers.json")
# 導(dǎo)入數(shù)據(jù)
with open("questions.json", "r") as fp:
questions = json.load(fp)
with open("answers.json", "r") as fp:
answers = json.load(fp)
from langchain.vectorstores import AnalyticDB
from langchain.embeddings import DashScopeEmbeddings
from langchain import VectorDBQA, OpenAI
embeddings = DashScopeEmbeddings(
model="text-embedding-v1", dashscope_api_key="your-dashscope-api-key"
)
doc_store = AnalyticDB.from_texts(
texts=answers, embedding=embeddings, connection_string=CONNECTION_STRING,
pre_delete_collection=True,
)
然后創(chuàng)建LangChain內(nèi)集成的tongyi模塊。
from langchain.chains import RetrievalQA
from langchain.llms import Tongyi
os.environ["DASHSCOPE_API_KEY"] = "your-dashscope-api-key"
llm = Tongyi()
查詢和檢索數(shù)據(jù),然后回答問題。
from langchain.prompts import PromptTemplate
custom_prompt = """
Use the following pieces of context to answer the question at the end. Please provide
a short single-sentence summary answer only. If you don't know the answer or if it's
not present in given context, don't try to make up an answer, but suggest me a random
unrelated song title I could listen to.
Context: {context}
Question: {question}
Helpful Answer:
"""
custom_prompt_template = PromptTemplate(
template=custom_prompt, input_variables=["context", "question"]
custom_qa = VectorDBQA.from_chain_type(
llm=llm,
chain_type="stuff",
vectorstore=doc_store,
return_source_documents=False,
chain_type_kwargs={"prompt": custom_prompt_template},
)
random.seed(41)
for question in random.choices(questions, k=5):
print(">", question)
print(custom_qa.run(question), end="\n\n")
> what was uncle jesse's original last name on full house
Uncle Jesse's original last name on Full House was Cochran.
> when did the volcano erupt in indonesia 2018
No information about a volcano erupting in Indonesia in 2018 is present in the given context. Suggested song title: "Volcano" by U2.
> what does a dualist way of thinking mean
A dualist way of thinking means believing that humans possess a non-physical mind or soul which is distinct from their physical body.
> the first civil service commission in india was set up on the basis of recommendation of
The first Civil Service Commission in India was not set up on the basis of a recommendation.
> how old do you have to be to get a tattoo in utah
In Utah, you must be at least 18 years old to get a tattoo.
在我們實(shí)際給用戶提供構(gòu)建一站式ChatBot的過程中,我們依然遇到了很多問題,比如文本切分過碎,導(dǎo)致語義丟失,文本包含圖表,切分后導(dǎo)致段落無法被理解等。
#大標(biāo)題1-中標(biāo)題1-小標(biāo)題1#:內(nèi)容1
#大標(biāo)題1-中標(biāo)題1-小標(biāo)題1#:內(nèi)容2
#大標(biāo)題1-中標(biāo)題1-小標(biāo)題2#:內(nèi)容1
#大標(biāo)題2-中標(biāo)題1-小標(biāo)題1#:內(nèi)容1
雖然我們做了很多優(yōu)化,但是由于用戶的文檔本身五花八門,現(xiàn)在依然無法找到一個(gè)完全通用的方案來應(yīng)對所有的數(shù)據(jù)源.比如某一切分器在markdown場景表現(xiàn)很好,但是對于pdf就效果下降得厲害。比如有的用戶還要求能夠在召回文本的同時(shí)召回圖片,視頻甚至ppt的slice.目前我們也只是通過metadata link的方式召回相關(guān)內(nèi)容,而不是把相關(guān)內(nèi)容直接做向量化。如果有同學(xué)有很好的辦法,歡迎在評論區(qū)交流。
以LLM構(gòu)建AI Agent是大語言模型的另一個(gè)典型的應(yīng)用場景。一些開源的非常火熱的項(xiàng)目,如AutoGPT、BabyAGI都是非常典型的示例。讓我們明白LLM的潛力不僅限于生成寫作精彩的文本、故事、文章等;它可以被視為一個(gè)強(qiáng)大的自我決策的系統(tǒng)。用AI做決策存在一定的風(fēng)險(xiǎn),但在一些簡單,只是處理繁瑣工作的場景,讓AI代替人工決策是可取的。
在以LLM為核心的自主代理系統(tǒng)中,LLM是Agent的大腦,我們還需要一些其他的組件來補(bǔ)全它的四肢。AI Agent主要借助思維鏈和思維樹的思想,提高Agent的思考和決策能力。
Planning
planning的作用有兩個(gè):
Memory
短期記憶:將所有上下文學(xué)習(xí)(參見提示工程)視為利用模型的短期記憶來學(xué)習(xí)。
長期記憶:這為代理提供了在長時(shí)間內(nèi)保留和檢索(無限)信息的能力,通常通過利用外部向量存儲和快速檢索來實(shí)現(xiàn)。
Tools
Tools模塊可以讓Agent調(diào)用外部API以獲取模型權(quán)重中缺失的額外信息(通常在預(yù)訓(xùn)練后難以更改),包括實(shí)時(shí)信息、代碼執(zhí)行能力、訪問專有信息源等。通常是通過設(shè)計(jì)API的方式讓LLM調(diào)用執(zhí)行。
一個(gè)復(fù)雜的任務(wù)通常包括許多步驟。代理需要知道這些步驟并提前規(guī)劃。
思維鏈(Chain of thought) (CoT; Wei et al. 2022)已經(jīng)成為提高模型在復(fù)雜任務(wù)上性能的標(biāo)準(zhǔn)提示技術(shù)。模型被指示“逐步思考”,以利用更多的測試時(shí)間計(jì)算來將困難任務(wù)分解成更小更簡單的步驟。CoT將大任務(wù)轉(zhuǎn)化為多個(gè)可管理的任務(wù),并揭示了模型思考過程的解釋。
思維樹(Tree of Thoughts) (Yao et al. 2023) 通過在每一步探索多種推理可能性來擴(kuò)展了CoT。它首先將問題分解為多個(gè)思維步驟,并在每一步生成多種思考,創(chuàng)建一個(gè)樹狀結(jié)構(gòu)。搜索過程可以是廣度優(yōu)先搜索(BFS)或深度優(yōu)先搜索(DFS),每個(gè)狀態(tài)都由分類器(通過提示)或多數(shù)投票進(jìn)行評估。
任務(wù)拆解可以通過以下方式完成:(1)LLM使用簡單的提示,如“完成任務(wù)X需要a、b、c的步驟。\n1。”,“實(shí)現(xiàn)任務(wù)X的子目標(biāo)是什么?”,(2)使用任務(wù)特定的指令;例如,“撰寫文案大綱。”,或者(3)通過交互式輸入指定需要操作的步驟。
自我反思(Self-Reflection)是一個(gè)非常重要的思想,它允許Agent通過改進(jìn)過去的行動(dòng)決策和糾正以前錯(cuò)誤的方式來不斷提高。在可以允許犯錯(cuò)和試錯(cuò)的現(xiàn)實(shí)任務(wù)中,它發(fā)揮著關(guān)鍵作用。比如寫一段某個(gè)用途的腳本代碼。
ReAct (Yao et al. 2023)通過將行動(dòng)空間擴(kuò)展為任務(wù)特定的離散行動(dòng)和語言空間的組合,將推理和行動(dòng)整合到LLM中。前者使LLM能夠與環(huán)境互動(dòng)(例如使用搜索引擎API),而后者促使LLM生成自然語言中的推理軌跡。
ReAct的prompt template包含了明確的步驟,供LLM思考,大致格式如下:
Thought: ...
Action: ...
Observation: ...
... (Repeated many times)
在對知識密集型任務(wù)和決策任務(wù)的兩個(gè)實(shí)驗(yàn)中,ReAct都表現(xiàn)比僅包含行動(dòng)(省略了“思考:…”步驟)更好的回答效果。
記憶可以定義為用于獲取、存儲、保留和以后檢索信息的過程。對于人類大腦,有幾種類型的記憶。
感覺記憶:這是記憶的最早階段,它使我們能夠在原始刺激結(jié)束后保留感覺信息(視覺、聽覺等)的能力。感覺記憶通常只持續(xù)幾秒鐘。子類別包括圖像記憶(視覺)、聲音記憶(聽覺)和觸覺記憶(觸覺)。
短期記憶(Short-Term Memory):它存儲我們當(dāng)前意識到的信息,需要執(zhí)行復(fù)雜的認(rèn)知任務(wù),如學(xué)習(xí)和推理。短期記憶的容量被認(rèn)為約為7個(gè)項(xiàng)目(Miller 1956),持續(xù)時(shí)間為20-30秒。
長期記憶(Long-Term Memory):長期記憶可以存儲信息很長時(shí)間,范圍從幾天到數(shù)十年,具有本質(zhì)上無限的存儲容量。長期記憶有兩個(gè)子類型:
顯式/陳述性記憶:這是關(guān)于事實(shí)和事件的記憶,指的是那些可以有意識地回憶起來的記憶,包括情節(jié)記憶(事件和經(jīng)歷)和語義記憶(事實(shí)和概念)。
隱式/程序性記憶:這種記憶是無意識的,涉及自動(dòng)執(zhí)行的技能和例行程序,如騎自行車,在鍵盤上打字等。
我們可以粗略地考慮以下映射關(guān)系:
感覺記憶是為原始輸入內(nèi)容(包括文本、圖像或其他模態(tài)),其可以在embedding之后作為輸入。
短期記憶就像上下文內(nèi)容,也就是聊天歷史,它是短暫而有限的,因?yàn)槭艿絋oken長度的限制。
長期記憶就像Agent可以在查詢時(shí)參考的外部向量存儲,可以通過快速檢索訪問。
外部存儲可以緩解有限注意力跨度的限制。一個(gè)標(biāo)準(zhǔn)的做法是將信息的嵌入表示保存到一個(gè)向量存儲數(shù)據(jù)庫中,該數(shù)據(jù)庫可以支持快速的最大內(nèi)積搜索(Maximum Inner Product Search)。為了優(yōu)化檢索速度,常見的選擇是使用近似最近鄰(ANN)算法,以返回近似的前k個(gè)最近鄰,可以在略微損失一些準(zhǔn)確性的情況下獲得巨大的速度提升。對于相似性算法有興趣的同學(xué)可以閱讀這篇文章《ChatGPT都推薦的向量數(shù)據(jù)庫,不僅僅是向量索引》。
使用工具可以使LLM完成一些其本身不能直接完成的事情。
Modular Reasoning, Knowledge and Language (Karpas et al. 2022)提出了一個(gè)MRKL系統(tǒng),包含一組專家模塊,通用的LLM作為路由器,將查詢路由到最合適的專家模塊。這些模塊可以是其他模型(文生圖,領(lǐng)域模型等)或功能模塊(例如數(shù)學(xué)計(jì)算器、貨幣轉(zhuǎn)換器、天氣API)。現(xiàn)在最典型的方式就是使用ChatGPT的function call功能。通過對ChatGPT注冊和描述接口的含義,就可以讓ChatGPT幫我們調(diào)用對應(yīng)的接口,返回正確的答案。
autogpt通過類似下面的prompt可以成功完成一些復(fù)雜的任務(wù),比如review開源項(xiàng)目的代碼,給開源項(xiàng)目代碼寫注釋。最近看到了Aone Copilot,其主要focus在代碼補(bǔ)全和代碼問答兩個(gè)場景。那么如果我們可以調(diào)用Aone Copilot的API,是否也可以在我們推送mr之后,讓agent幫我們完成一些代碼風(fēng)格,語法校驗(yàn)的代碼review工作,和單元測試用例編寫工作。
You are {{ai-name}}, {{user-provided AI bot description}}.
Your decisions must always be made independently without seeking user assistance. Play to your strengths as an LLM and pursue simple strategies with no legal complications.
GOALS:
1. {{user-provided goal 1}}
2. {{user-provided goal 2}}
3. ...
4. ...
5. ...
Constraints:
1. ~4000 word limit for short term memory. Your short term memory is short, so immediately save important information to files.
2. If you are unsure how you previously did something or want to recall past events, thinking about similar events will help you remember.
3. No user assistance
4. Exclusively use the commands listed in double quotes e.g. "command name"
5. Use subprocesses for commands that will not terminate within a few minutes
Commands:
1. Google Search: "google", args: "input": "<search>"
2. Browse Website: "browse_website", args: "url": "<url>", "question": "<what_you_want_to_find_on_website>"
3. Start GPT Agent: "start_agent", args: "name": "<name>", "task": "<short_task_desc>", "prompt": "<prompt>"
4. Message GPT Agent: "message_agent", args: "key": "<key>", "message": "<message>"
5. List GPT Agents: "list_agents", args:
6. Delete GPT Agent: "delete_agent", args: "key": "<key>"
7. Clone Repository: "clone_repository", args: "repository_url": "<url>", "clone_path": "<directory>"
8. Write to file: "write_to_file", args: "file": "<file>", "text": "<text>"
9. Read file: "read_file", args: "file": "<file>"
10. Append to file: "append_to_file", args: "file": "<file>", "text": "<text>"
11. Delete file: "delete_file", args: "file": "<file>"
12. Search Files: "search_files", args: "directory": "<directory>"
13. Analyze Code: "analyze_code", args: "code": "<full_code_string>"
14. Get Improved Code: "improve_code", args: "suggestions": "<list_of_suggestions>", "code": "<full_code_string>"
15. Write Tests: "write_tests", args: "code": "<full_code_string>", "focus": "<list_of_focus_areas>"
16. Execute Python File: "execute_python_file", args: "file": "<file>"
17. Generate Image: "generate_image", args: "prompt": "<prompt>"
18. Send Tweet: "send_tweet", args: "text": "<text>"
19. Do Nothing: "do_nothing", args:
20. Task Complete (Shutdown): "task_complete", args: "reason": "<reason>"
Resources:
1. Internet access for searches and information gathering.
2. Long Term memory management.
3. GPT-3.5 powered Agents for delegation of simple tasks.
4. File output.
Performance Evaluation:
1. Continuously review and analyze your actions to ensure you are performing to the best of your abilities.
2. Constructively self-criticize your big-picture behavior constantly.
3. Reflect on past decisions and strategies to refine your approach.
4. Every command has a cost, so be smart and efficient. Aim to complete tasks in the least number of steps.
You should only respond in JSON format as described below
Response Format:
{
"thoughts": {
"text": "thought",
"reasoning": "reasoning",
"plan": "- short bulleted\n- list that conveys\n- long-term plan",
"criticism": "constructive self-criticism",
"speak": "thoughts summary to say to user"
},
"command": {
"name": "command name",
"args": {
"arg name": "value"
}
}
}
Ensure the response can be parsed by Python json.loads
LangChain已經(jīng)內(nèi)置了很多agent實(shí)現(xiàn)的框架模塊,主要包含:
toolkits主要通過注冊機(jī)制向agent返回一系列可以調(diào)用的tool。其基類代碼為BaseToolkit。
class BaseToolkit(BaseModel, ABC):
"""Base Toolkit representing a collection of related tools."""
@abstractmethod
def get_tools(self) -> List[BaseTool]:
"""Get the tools in the toolkit."""
我們可以通過繼承BaseToolkit的方式來實(shí)現(xiàn)不同的toolkit,每一個(gè)toolkit都會實(shí)現(xiàn)一系列的tools,一個(gè)Tool則包含幾個(gè)部分,必須要包含的內(nèi)容有name,description。通過這幾個(gè)字段來告知LLM這個(gè)工具的作用和調(diào)用方法,這里就要求注冊的tool最好能夠通過name明確表達(dá)其用途,同時(shí)也可以在description中增加few-shot來做調(diào)用example,使得LLM能夠更好地理解tool。同時(shí)在LangChain內(nèi)部已經(jīng)集成了很多工具,我們可以直接調(diào)用這些工具來組成Tools。
class BaseTool(BaseModel, Runnable[Union[str, Dict], Any]):
name: str
"""The unique name of the tool that clearly communicates its purpose."""
description: str
"""Used to tell the model how/when/why to use the tool.
You can provide few-shot examples as a part of the description.
"""
...
class Tool(BaseTool):
"""Tool that takes in function or coroutine directly."""
description: str = ""
func: Optional[Callable[..., str]]
"""The function to run when the tool is called."""
接下來我們做一個(gè)簡單的agent demo,這個(gè)agent主要做兩件事情。
1. 從網(wǎng)上檢索收集問題需要的數(shù)據(jù)
2.利用收集到的數(shù)據(jù)進(jìn)行科學(xué)計(jì)算,回答用戶的問題。
在這個(gè)流程中,我們主要用到Search和Calculator兩個(gè)工具。
from langchain.agents import initialize_agent, AgentType, Tool
from langchain.chains import LLMMathChain
from langchain.chat_models import ChatOpenAI
from langchain.llms import OpenAI
from langchain.utilities import SerpAPIWrapper
llm = ChatOpenAI(temperature=0, model="gpt-3.5-turbo-0613")
search = SerpAPIWrapper()
llm_math_chain = LLMMathChain.from_llm(llm=llm, verbose=True)
tools = [
Tool(
name = "Search",
func=search.run,
description="useful for when you need to answer questions about current events. You should ask targeted questions"
),
Tool(
name="Calculator",
func=llm_math_chain.run,
description="useful for when you need to answer questions about math"
)
]
agent = initialize_agent(tools, llm, agent=AgentType.OPENAI_FUNCTIONS, verbose=True)
agent.run("Who is Leo DiCaprio's girlfriend? What is her current age raised to the 0.43 power?")
> Entering new chain...
Invoking: Search
with {'query': 'Leo DiCaprio girlfriend'}
Amidst his casual romance with Gigi, Leo allegedly entered a relationship with 19-year old model, Eden Polani, in February 2023.
Invoking: Calculator
with {'expression': '19^0.43'}
> Entering new chain...
19^0.43```text
19**0.43
```
...numexpr.evaluate("19**0.43")...
Answer: 3.547023357958959
> Finished chain.
Answer: 3.547023357958959Leo DiCaprio's girlfriend is reportedly Eden Polani. Her current age raised to the power of 0.43 is approximately 3.55.
> Finished chain.
"Leo DiCaprio's girlfriend is reportedly Eden Polani. Her current age raised to the power of 0.43 is approximately 3.55."
可以看到,這個(gè)agent可以成功地完成意圖檢索尋求知識和科學(xué)計(jì)算得到結(jié)果。
這個(gè)case是結(jié)合大模型和數(shù)據(jù)庫,通過查詢表里的數(shù)據(jù)來回答用戶問題,用的關(guān)鍵prompt為
_postgres_prompt = """You are a PostgreSQL expert. Given an input question, first create a syntactically correct PostgreSQL query to run, then look at the results of the query and return the answer to the input question.
Unless the user specifies in the question a specific number of examples to obtain, query for at most {top_k} results using the LIMIT clause as per PostgreSQL. You can order the results to return the most informative data in the database.
Never query for all columns from a table. You must query only the columns that are needed to answer the question. Wrap each column name in double quotes (") to denote them as delimited identifiers.
Pay attention to use only the column names you can see in the tables below. Be careful to not query for columns that do not exist. Also, pay attention to which column is in which table.
Pay attention to use CURRENT_DATE function to get the current date, if the question involves "today".
Use the following format:
Question: Question here
SQLQuery: SQL Query to run
SQLResult: Result of the SQLQuery
Answer: Final answer here
"""
下面是實(shí)際的工作代碼,目前在這個(gè)場景,openai的推理能力最強(qiáng),能夠正確完成這個(gè)復(fù)雜的Agent工作。
## export your openai key first export OPENAI_API_KEY=sk-xxxxx
from langchain.agents import create_sql_agent
from langchain.agents.agent_toolkits import SQLDatabaseToolkit
from langchain.agents import AgentExecutor
from langchain.llms.tongyi import Tongyi
from langchain.sql_database import SQLDatabase
import psycopg2cffi as psycopg2 # pip install psycopg-binary if on linux, just use psycopg2
from langchain.chat_models import ChatOpenAI
db = SQLDatabase.from_uri('postgresql+psycopg2cffi://admin:password123@localhost/admin')
llm = ChatOpenAI(model_name="gpt-3.5-turbo")
toolkit = SQLDatabaseToolkit(db=db,llm=llm)
agent_executor = create_sql_agent(
llm=llm,
toolkit=toolkit,
verbose=True
)
agent_executor.run("using the teachers table, find the first_name and last name of teachers who earn less the mean salary?")
可以看到大模型經(jīng)過多輪思考,正確回答了我們的問題。
> Entering new AgentExecutor chain...
Action: sql_db_list_tables
Action Input: ""
Observation: teachers
Thought:I can query the "teachers" table to find the first_name and last_name columns.
Action: sql_db_schema
Action Input: "teachers"
Observation:
CREATE TABLE teachers (
id INTEGER,
first_name VARCHAR(25),
last_name VARCHAR(50),
school VARCHAR(50),
hire_data DATE,
salary NUMERIC
)
/*
3 rows from teachers table:
id first_name last_name school hire_data salary
None Janet Smith F.D. Roosevelt HS 2011-10-30 36200
None Lee Reynolds F.D. Roosevelt HS 1993-05-22 65000
None Samuel Cole Myers Middle School 2005-08-01 43500
*/
Thought:I can now construct a query to find the first_name and last_name of teachers who earn less than the mean salary.
Action: sql_db_query
Action Input: "SELECT first_name, last_name FROM teachers WHERE salary < (SELECT AVG(salary) FROM teachers) LIMIT 10"
Observation: [('Janet', 'Smith'), ('Samuel', 'Cole'), ('Samantha', 'Bush'), ('Betty', 'Diaz'), ('Kathleen', 'Roush')]
Thought:Retrying langchain.chat_models.openai.ChatOpenAI.completion_with_retry.<locals>._completion_with_retry in 4.0 seconds as it raised RateLimitError: Rate limit reached for default-gpt-3.5-turbo in organization org-FDYSniIsv0FIQBi9p4P9Dinn on requests per min. Limit: 3 / min. Please try again in 20s. Contact us through our help center at help.openai.com if you continue to have issues. Please add a payment method to your account to increase your rate limit. Visit https://platform.openai.com/account/billing to add a payment method..
Retrying langchain.chat_models.openai.ChatOpenAI.completion_with_retry.<locals>._completion_with_retry in 4.0 seconds as it raised RateLimitError: Rate limit reached for default-gpt-3.5-turbo in organization org-FDYSniIsv0FIQBi9p4P9Dinn on requests per min. Limit: 3 / min. Please try again in 20s. Contact us through our help center at help.openai.com if you continue to have issues. Please add a payment method to your account to increase your rate limit. Visit https://platform.openai.com/account/billing to add a payment method..
Retrying langchain.chat_models.openai.ChatOpenAI.completion_with_retry.<locals>._completion_with_retry in 4.0 seconds as it raised RateLimitError: Rate limit reached for default-gpt-3.5-turbo in organization org-FDYSniIsv0FIQBi9p4P9Dinn on requests per min. Limit: 3 / min. Please try again in 20s. Contact us through our help center at help.openai.com if you continue to have issues. Please add a payment method to your account to increase your rate limit. Visit https://platform.openai.com/account/billing to add a payment method..
Retrying langchain.chat_models.openai.ChatOpenAI.completion_with_retry.<locals>._completion_with_retry in 8.0 seconds as it raised RateLimitError: Rate limit reached for default-gpt-3.5-turbo in organization org-FDYSniIsv0FIQBi9p4P9Dinn on requests per min. Limit: 3 / min. Please try again in 20s. Contact us through our help center at help.openai.com if you continue to have issues. Please add a payment method to your account to increase your rate limit. Visit https://platform.openai.com/account/billing to add a payment method..
The first_name and last_name of teachers who earn less than the mean salary are Janet Smith, Samuel Cole, Samantha Bush, Betty Diaz, and Kathleen Roush.
Final Answer: Janet Smith, Samuel Cole, Samantha Bush, Betty Diaz, Kathleen Roush
> Finished chain.
'Janet Smith, Samuel Cole, Samantha Bush, Betty Diaz, Kathleen Roush'
和ChatBot不同,agent的構(gòu)建是對LLM的推理能力提出了更高的要求。ChatBot的回答可能是不正確的,但這依然可以通過人類的判別回饋來確定問答結(jié)果是否有益,對于無效的回答可以容忍地直接忽略或者重新回答。 但是agent對模型的錯(cuò)誤判斷的容忍度則更低。雖然我們可以通過自我反思機(jī)制減少agent的出錯(cuò)率,但是其當(dāng)前可以應(yīng)用的場景依然較小。需要我們不斷去探索和開拓新的場景,同時(shí)不斷提高大模型的推理能力,從而能夠搭建更加復(fù)雜的agent。
同時(shí),agent目前能夠在比較小的場景勝任工作,比如我們的意圖是明確的,同時(shí)也只給agent提供了比較少量的toolkit來執(zhí)行任務(wù)(10個(gè)以內(nèi)),且每個(gè)tool的用差異明顯,在這種情況下,LLM能夠正確選擇tool進(jìn)行任務(wù),并得到期望的結(jié)果。但是當(dāng)一個(gè)agent里注冊了上百個(gè)甚至更多工具時(shí),LLM就可能無法正確地選擇tool執(zhí)行操作了。這里的一個(gè)解法是通過多層agent樹的方式來解決,父agent負(fù)責(zé)路由分發(fā)任務(wù)給不同的子agent。每一個(gè)子agent則僅僅包含和使用有限的toolkit來執(zhí)行任務(wù),從而提高agent復(fù)雜場景的任務(wù)完成率。
云原生數(shù)據(jù)倉庫 AnalyticDB 是一種大規(guī)模并行處理數(shù)據(jù)倉庫服務(wù),可提供海量數(shù)據(jù)在線分析服務(wù)。在云原生數(shù)據(jù)倉庫能力上全自研企業(yè)級向量引擎,支持流式向量數(shù)據(jù)寫入、百億級向量數(shù)據(jù)檢索;支持結(jié)構(gòu)化數(shù)據(jù)分析、向量檢索和全文檢索多路召回,支持對接通義千問等國內(nèi)外主流大模型。
了解更多 AnalyticDB 介紹和相關(guān)解決方案請參考:
AnalyticDB向量引擎介紹:https://www.aliyun.com/activity/database/adbpg_vector
一鍵部署PAI+通義千問+AnalyticDB向量引擎搭建ChatBot:https://computenest.console.aliyun.com/user/cn-hangzhou/serviceInstanceCreate?ServiceId=service-ddfecdd9b626465f85b6
文章轉(zhuǎn)自微信公眾號@阿里云開發(fā)者
GraphRAG:基于PolarDB+通義千問api+LangChain的知識圖譜定制實(shí)踐
使用Node.js、Express和MySQL構(gòu)建REST API
天氣API推薦:精準(zhǔn)獲取氣象數(shù)據(jù)的首選
基于自定義數(shù)據(jù)集的微調(diào):Alpaca與LLaMA模型的訓(xùn)練
OAuth和OpenID Connect圖解指南
有哪些新聞媒體提供Open API?
現(xiàn)在做大模型,還有靠譜且免費(fèi)的API接口嗎?
如何運(yùn)用AI提高自己的工作效率?
區(qū)塊鏈API推薦,快速開發(fā)去中心化應(yīng)用