青训营X豆包MarsCode AI训练营12-16课 | 豆包MarsCode AI 刷题

142 阅读4分钟

主要学习了代理,以及RAG应用的更高级应用,以及实现了一个新的数据库应用开发范式

代理

  • 思维链无法主动更新自己知识,解决大模型“事实幻觉”:先本地知识库找否则外部搜索
  • 代理根据输入决定调用哪些外部工具(数据清洗、搜索引擎、应用程序)

ReAct

  • 基于推理reasoning行动Acting之间协同作用生成任务轨迹:观察-思考-行动
  • 利用SERPAPI_API_KEY作为Google搜索工具
 # 老版本
 os.environ["SERPAPI_API_KEY"] = ("xx")
 tools = load_tools(["serpapi", "llm-math"], llm=llm)
 agent = initialize_agent(tools, llm, agent=AgentType.ZERO_SHOT_REACT_DESCRIPTION, verbose=True)
 agent.invoke("xxx")
 # thought > action > action input > observation > thought > final answer
 # 新版本
 tools = load_tools(["serpapi", "llm-math"], llm=llm)
 ​
 prompt = hub.pull("hwchase17/react")
 agent = create_react_agent(llm, tools, prompt)
 agent_executor = AgentExecutor(agent=agent, tools=tools, verbose=True)
 ​
 agent_executor.invoke({"input": "xx"})

Structured Tool Chat

  • Playwright工具包,模拟真实用户操作网页
 # 使用playwright访问网页
 from playwright.sync_api import sync_playwright
 ​
 with sync_playwright() as p:
     browser = p.chromium.lauch()
     page = browser.new_page()
     page.goto("https://xx.com/")
     title = page.title()
     browser.close()
  • 结构化工具对话代理——浏览器自动化工具链
 async_browser = create_async_playwright_browser()
 toolkit = PlayWrightBrowserToolkit.from_browser(async_browser=async_browser)
 tools = toolkit.get_tools()
 ​
 llm = xxx
 agent_chain = initialize_agent(
     tools,
     llm,
     # 基于输入的自然语言指令,智能选择适当的工具执行任务
     agent=AgentType.STRUCTURED_CHAT_ZERO_SHOT_REACT_DESCIPTION,
     verbose=True,
 )
 ​
 async def main():
     response = await agent_chain.ainvoke("xxx")
 ​
 loop = asyncio.get_event_loop()
 loop.run_until_complete(main())

Self-Ask with Search

  • 自主询问搜索代理, Follow-up Question追问+Intermediate Answer中间答案,来辅助llm寻找事实性问题的过渡性答案
  • 多跳问题(Multi-hop question)引出最终答案
 search = SerpAPIWrapper()
 tools = [
     Tool(
         name="Intermediate Answer",
         func=search.run,
         description="useful for when you need to ask with search",
     )
 ]
 ​
 self_ask_with_search = initialize_agent(
     tools, llm, agent=AgentType.SELF_ASK_WITH_SEARCH, verbose=True
 )
 self_ask_with_search.run("xxx?")

Plan and execute

  • 计划与执行代理,计划由一个大语言模型代理(负责推理)完成,执行由另一个大语言模型代理(负责调用工具)完成
 search = SerpAPIWrapper()
 llm = ChatOpenAI(model=os.environ["LLM_MODELEND"], temperature=0)
 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",
     ),
     Tool(
         name="Calculator",
         func=llm_math_chain.run,
         description="useful for when you need to answer questions about math",
     ),
 ]
 ​
 model = ChatOpenAI(model=os.environ["LLM_MODELEND"], temperature=0)
 ​
 planner = load_chat_planner(model)
 executor = load_agent_executor(model, tools, verbose=True)
 agent = PlanAndExecute(planner=planner, executor=executor, verbose=True)
 ​
 agent.invoke("xx?")

工具

 tools = load_tools(["arxiv"],) # 论文研究

RAG

Retrieval-Augmented Generation,检索增强生成

  • 检索:对于给定的输入从大型文档集合中查找文档,基于密集向量搜索
  • 上下文编码:将文档与原始输入一起编码
  • 生成:模型生成输出

文档加载

 # TextLoader
 loader = TextLoader("./x.txt", encoding="utf8")
 # CSVLoader
 # HTMLLoader
 # JSONLoader
 # MarkdownLoader
 # PDFLoader

文本转换

长文档分割成小的块,适合模型的上下文窗口

文本分割器

  1. 将文本分成小的、有语义意义的块(句子),将小块组合成更大的块直到达到一定大小形成块
  2. 创建新的文本块与块有重叠来保持块之间上下文

文本嵌入

LLM来对文本块做嵌入(Embeddings),创建一段文本的向量表示,使可以在向量空间中思考文本并执行语义搜索操作,在向量空间查找最相似的文本片段

Langchain中Embeddings类设计用于与文本嵌入模型交互

 from langchain_community.embeddings import OpenAIEmbeddings
 embeddings_model = OpenAIEmbeddings()
  • embed_documents方法:为文档创建嵌入,接收多个文本输入,一次性将文档转换为向量表示
  •  embeddings = embeddings_model.embed_documents(
         "a""b""c",     ]
     ) # return [1,2,3,4]
    
  • embed_query方法:为查询创建嵌入,接收一个文本作为输入,为用户的搜索查询
  •  embedded_query = embeddings_model.embed_query("a?")
    

存储嵌入

缓存存储:CacheBackedEmbeddings是一个支持缓存的嵌入式包装器,嵌入缓存在键值存储中:对文本进行哈希处理作为键

缓存策略

  • InMemoryStore:内存中缓存,用于单元测试
  • LocalFileStore:本地文件系统存储
  • RedisStore:在Redis数据库中缓存嵌入,高速可扩展
 store = InMemoryStore()
 embedder = CacheBackedEmbeddings.from_bytes_store(
     underlying_embeddings, # 实际生成文本嵌入的工具
     store, # 嵌入的缓存位置
     namespace=underlying_embeddings.model # 嵌入缓存的命名空间
 )
 embeddings = embdder.embed_documents(["first", "second"]) # embbeder为文本生成嵌入,结果向量存储在内存存储中

向量存储:通过向量数据库(Vector Store)保存

数据检索

通过非结构化查询返回相关文档,向量存储检索器支持向量检索

 index = VectorstoreIndexCreator(embedding=embeddings).from_loaders([loader])
 # 创建索引来查询检索
 query = "xxx是什么?"
 result = index.query(llm=llm, question=query)

数据库应用

Chain 查询

 db = SQLDatabase.from_uri("sqlite:///test.db") # 连接数据库
 # 温度0: 模型输出更具确定性
 llm = ChatOpenAI(model=os.environ["LLM_MODELEND"], temperature=0, verbose=True)
 db_chain = SQLDatabaseChain.from_llm(llm, db, verbose=True)
 response = db_chain.run("xxx?")

Agent 查询数据库

具有纠错能力

 db = SQLDatabase.from_uri("sqlite:///test.db")
 llm = ...
 # 创建SQL Agent
 agent_executor = create_sql_agent(
     llm=llm,
     toolkit=SQLDatabaseToolkit(db=db, llm=llm),
     verbose=True,
     agent_type=AgentType.ZERO_SHOT_REACT_DESCRIPTION,
 )
 ​
 questions = ["q1?","q2?",]
 ​
 for question in questions:
     response = agent_executor.invoke(question)