mirror of
https://github.com/langchain-ai/langgraph.git
synced 2026-09-02 14:28:46 +02:00
28 KiB
28 KiB
In [1]:
from operator import itemgetter
from langchain.chat_models import ChatOpenAI, ChatAnthropic
from langchain.prompts import SystemMessagePromptTemplate, ChatPromptTemplate
from langchain.schema.output_parser import StrOutputParser
from langchain.runnables.openai_functions import OpenAIFunctionsRouter
from permchain.connection_inmemory import InMemoryPubSubConnection
from permchain.pubsub import PubSub
from permchain.topic import TopicIn [2]:
from langchain.utilities import GoogleSearchAPIWrapper
from langchain.document_loaders import AsyncHtmlLoader
from langchain.document_transformers import Html2TextTransformerIn [3]:
from duckduckgo_search import DDGS
ddgs = DDGS()In [4]:
def retrieve_documents(query):
query = query.strip().strip('"')
search_results = ddgs.text(query)
urls_to_look = []
for res in search_results:
if res.get("href", None):
urls_to_look.append(res["href"])
if len(urls_to_look) >= 4:
break
# Relevant urls
# Load, split, and add new urls to vectorstore
if urls_to_look:
loader = AsyncHtmlLoader(urls_to_look)
html2text = Html2TextTransformer()
docs = loader.load()
docs = list(html2text.transform_documents(docs))
else:
docs = []
return docsIn [5]:
import nest_asyncio
nest_asyncio.apply()In [6]:
# docs = retrieve_documents("langchain")In [24]:
prompt = ChatPromptTemplate.from_template(
"Answer the user's question given the search results\n\n<question>{question}</question><search_results>{search_results}</search_results>"
)In [25]:
summarizer_chain = (
prompt
| ChatOpenAI(max_retries=0).with_fallbacks(
[ChatOpenAI(model="gpt-3.5-turbo-16k"), ChatAnthropic(model="claude-2")]
)
| StrOutputParser()
)In [26]:
summarizer_inbox = Topic("summarizer")In [27]:
search_actor = (
Topic.IN.subscribe()
| {
"search_results": retrieve_documents,
"question": Topic.IN.current(),
}
| summarizer_inbox.publish()
)In [43]:
summ_actor = (
summarizer_inbox.subscribe() | {"answer": summarizer_chain} | Topic.OUT.publish()
)In [44]:
web_researcher = PubSub(
processes=(search_actor, summ_actor),
connection=InMemoryPubSubConnection(),
)In [45]:
web_researcher.invoke("What is langsmith?")Out [45]:
Fetching pages: 100%|#############################################################################################################################################################################################| 4/4 [00:00<00:00, 6.44it/s]
[{'answer': 'LangSmith is a platform for building production-grade language model applications. It helps trace and evaluate language model applications and intelligent agents, making it easier to move from prototype to production. LangSmith is developed by LangChain, the company behind the open source LangChain framework. More information can be found in the LangSmith documentation.'}]In [47]:
web_researcher.batch(["what is langsmith", "what is llama"])Fetching pages: 0%| | 0/4 [00:00<?, ?it/s]
Fetching pages: 100%|#############################################################################################################################################################################################| 4/4 [00:00<00:00, 6.93it/s][A
Fetching pages: 100%|#############################################################################################################################################################################################| 4/4 [00:00<00:00, 4.79it/s]
[0;31m---------------------------------------------------------------------------[0m [0;31mTypeError[0m Traceback (most recent call last) Cell [0;32mIn[47], line 1[0m [0;32m----> 1[0m [43mweb_researcher[49m[38;5;241;43m.[39;49m[43mbatch[49m[43m([49m[43m[[49m[38;5;124;43m"[39;49m[38;5;124;43mwhat is langsmith[39;49m[38;5;124;43m"[39;49m[43m,[49m[43m [49m[38;5;124;43m"[39;49m[38;5;124;43mwhat is llama[39;49m[38;5;124;43m"[39;49m[43m][49m[43m)[49m File [0;32m~/workplace/langchain/libs/langchain/langchain/schema/runnable/base.py:102[0m, in [0;36mRunnable.batch[0;34m(self, inputs, config, max_concurrency)[0m [1;32m 99[0m [38;5;28;01mreturn[39;00m [[38;5;28mself[39m[38;5;241m.[39minvoke(inputs[[38;5;241m0[39m], configs[[38;5;241m0[39m])] [1;32m 101[0m [38;5;28;01mwith[39;00m ThreadPoolExecutor(max_workers[38;5;241m=[39mmax_concurrency) [38;5;28;01mas[39;00m executor: [0;32m--> 102[0m [38;5;28;01mreturn[39;00m [38;5;28;43mlist[39;49m[43m([49m[43mexecutor[49m[38;5;241;43m.[39;49m[43mmap[49m[43m([49m[38;5;28;43mself[39;49m[38;5;241;43m.[39;49m[43minvoke[49m[43m,[49m[43m [49m[43minputs[49m[43m,[49m[43m [49m[43mconfigs[49m[43m)[49m[43m)[49m File [0;32m~/.pyenv/versions/3.10.1/lib/python3.10/concurrent/futures/_base.py:608[0m, in [0;36mExecutor.map.<locals>.result_iterator[0;34m()[0m [1;32m 605[0m [38;5;28;01mwhile[39;00m fs: [1;32m 606[0m [38;5;66;03m# Careful not to keep a reference to the popped future[39;00m [1;32m 607[0m [38;5;28;01mif[39;00m timeout [38;5;129;01mis[39;00m [38;5;28;01mNone[39;00m: [0;32m--> 608[0m [38;5;28;01myield[39;00m [43mfs[49m[38;5;241;43m.[39;49m[43mpop[49m[43m([49m[43m)[49m[38;5;241;43m.[39;49m[43mresult[49m[43m([49m[43m)[49m [1;32m 609[0m [38;5;28;01melse[39;00m: [1;32m 610[0m [38;5;28;01myield[39;00m fs[38;5;241m.[39mpop()[38;5;241m.[39mresult(end_time [38;5;241m-[39m time[38;5;241m.[39mmonotonic()) File [0;32m~/.pyenv/versions/3.10.1/lib/python3.10/concurrent/futures/_base.py:445[0m, in [0;36mFuture.result[0;34m(self, timeout)[0m [1;32m 443[0m [38;5;28;01mraise[39;00m CancelledError() [1;32m 444[0m [38;5;28;01melif[39;00m [38;5;28mself[39m[38;5;241m.[39m_state [38;5;241m==[39m FINISHED: [0;32m--> 445[0m [38;5;28;01mreturn[39;00m [38;5;28;43mself[39;49m[38;5;241;43m.[39;49m[43m__get_result[49m[43m([49m[43m)[49m [1;32m 446[0m [38;5;28;01melse[39;00m: [1;32m 447[0m [38;5;28;01mraise[39;00m [38;5;167;01mTimeoutError[39;00m() File [0;32m~/.pyenv/versions/3.10.1/lib/python3.10/concurrent/futures/_base.py:390[0m, in [0;36mFuture.__get_result[0;34m(self)[0m [1;32m 388[0m [38;5;28;01mif[39;00m [38;5;28mself[39m[38;5;241m.[39m_exception: [1;32m 389[0m [38;5;28;01mtry[39;00m: [0;32m--> 390[0m [38;5;28;01mraise[39;00m [38;5;28mself[39m[38;5;241m.[39m_exception [1;32m 391[0m [38;5;28;01mfinally[39;00m: [1;32m 392[0m [38;5;66;03m# Break a reference cycle with the exception in self._exception[39;00m [1;32m 393[0m [38;5;28mself[39m [38;5;241m=[39m [38;5;28;01mNone[39;00m File [0;32m~/.pyenv/versions/3.10.1/lib/python3.10/concurrent/futures/thread.py:58[0m, in [0;36m_WorkItem.run[0;34m(self)[0m [1;32m 55[0m [38;5;28;01mreturn[39;00m [1;32m 57[0m [38;5;28;01mtry[39;00m: [0;32m---> 58[0m result [38;5;241m=[39m [38;5;28;43mself[39;49m[38;5;241;43m.[39;49m[43mfn[49m[43m([49m[38;5;241;43m*[39;49m[38;5;28;43mself[39;49m[38;5;241;43m.[39;49m[43margs[49m[43m,[49m[43m [49m[38;5;241;43m*[39;49m[38;5;241;43m*[39;49m[38;5;28;43mself[39;49m[38;5;241;43m.[39;49m[43mkwargs[49m[43m)[49m [1;32m 59[0m [38;5;28;01mexcept[39;00m [38;5;167;01mBaseException[39;00m [38;5;28;01mas[39;00m exc: [1;32m 60[0m [38;5;28mself[39m[38;5;241m.[39mfuture[38;5;241m.[39mset_exception(exc) File [0;32m~/workplace/permchain/permchain/pubsub.py:67[0m, in [0;36mPubSub.invoke[0;34m(self, input, config)[0m [1;32m 65[0m [38;5;28;01mdef[39;00m [38;5;21minvoke[39m([38;5;28mself[39m, [38;5;28minput[39m: Any, config: Optional[RunnableConfig] [38;5;241m=[39m [38;5;28;01mNone[39;00m) [38;5;241m-[39m[38;5;241m>[39m Any: [1;32m 66[0m collected [38;5;241m=[39m [] [0;32m---> 67[0m [38;5;28;01mfor[39;00m chunk [38;5;129;01min[39;00m [38;5;28mself[39m[38;5;241m.[39mstream([38;5;28minput[39m, config): [1;32m 68[0m collected[38;5;241m.[39mappend(chunk) [1;32m 69[0m [38;5;28;01mreturn[39;00m collected File [0;32m~/workplace/permchain/permchain/pubsub.py:176[0m, in [0;36mPubSub.stream[0;34m(self, input, config, max_concurrency)[0m [1;32m 174[0m final_output [38;5;241m=[39m chunk [1;32m 175[0m [38;5;28;01melse[39;00m: [0;32m--> 176[0m final_output [38;5;241m+[39m[38;5;241m=[39m chunk [1;32m 177[0m [38;5;28;01mfinally[39;00m: [1;32m 178[0m [38;5;66;03m# Cleanup[39;00m [1;32m 179[0m [38;5;28;01mfor[39;00m fut [38;5;129;01min[39;00m inflight: [0;31mTypeError[0m: unsupported operand type(s) for +=: 'dict' and 'dict'
In [31]:
from langchain.output_parsers.openai_functions import JsonKeyOutputFunctionsParserIn [32]:
template = """Write between 2 and 5 sub questions that serve as google search queries to search online that form an objective opinion from the following: {question}"""
functions = [
{
"name": "sub_questions",
"description": "List of sub questions",
"parameters": {
"type": "object",
"properties": {
"questions": {
"type": "array",
"description": "List of sub questions to ask.",
"items": {"type": "string"},
},
},
},
},
]
prompt = ChatPromptTemplate.from_template(template)
question_chain = (
prompt
| ChatOpenAI(temperature=0).bind(
functions=functions, function_call={"name": "sub_questions"}
)
| JsonKeyOutputFunctionsParser(key_name="questions")
)In [33]:
question_chain.invoke({"question": "what is langsmith?"})Out [33]:
['What is the purpose of Langsmith?', 'Who developed Langsmith?', 'What are the features of Langsmith?', 'How does Langsmith work?', 'Are there any alternatives to Langsmith?']
In [34]:
template = """You are tasked with writing a research report to answer the following question:
<question>
{question}
</question>
In order to do that, you first came up with several sub questions and researched those. please find those below:
<research>
{research}
</research>
Now, write your final report answering the original question!"""
prompt = ChatPromptTemplate.from_template(template)
report_chain = prompt | ChatOpenAI() | StrOutputParser()In [35]:
research_inbox = Topic("research")
writer_inbox = Topic("writer_inbox")In [36]:
subquestion_actor = (
# Listed in inputs
Topic.IN.subscribe()
| question_chain
# The draft always goes to the editors inbox
| research_inbox.publish()
)
research_actor = (
research_inbox.subscribe()
| {
"research": lambda x: web_researcher.batch(x),
# "research": lambda x: [web_researcher.invoke({"question": i}) for i in x],
"question": Topic.IN.current() | itemgetter("question"),
}
| writer_inbox.publish()
)
write_actor = writer_inbox.subscribe() | report_chain | Topic.OUT.publish()In [37]:
longer_researcher = PubSub(
processes=(subquestion_actor, research_actor, write_actor),
connection=InMemoryPubSubConnection(),
)In [38]:
longer_researcher.invoke({"question": "what is langsmith?"})Out [38]:
Fetching pages: 0%| | 0/4 [00:00<?, ?it/s] Fetching pages: 0%| | 0/4 [00:00<?, ?it/s][A Fetching pages: 0%| | 0/4 [00:00<?, ?it/s][A[A Fetching pages: 0%| | 0/4 [00:00<?, ?it/s][A[A[A Fetching pages: 0%| | 0/4 [00:00<?, ?it/s][A[A[A[A Fetching pages: 100%|#######################################################################################################################################################################################| 4/4 [00:01<00:00, 3.84it/s][A Fetching pages: 100%|#######################################################################################################################################################################################| 4/4 [00:01<00:00, 3.64it/s][A[A[A[A Fetching pages: 100%|#######################################################################################################################################################################################| 4/4 [00:01<00:00, 2.88it/s] Fetching pages: 100%|#######################################################################################################################################################################################| 4/4 [00:01<00:00, 2.85it/s][A[A[A Fetching pages: 100%|#######################################################################################################################################################################################| 4/4 [00:01<00:00, 2.69it/s][A[A 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-16k in organization org-i0zjYONU3PemzJ222esBaAzZ on tokens per min. Limit: 180000 / min. Current: 173743 / min. Contact us through our help center at help.openai.com if you continue to have issues.. 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-16k in organization org-i0zjYONU3PemzJ222esBaAzZ on tokens per min. Limit: 180000 / min. Current: 161254 / min. Contact us through our help center at help.openai.com if you continue to have issues..
['Research Report: Understanding LangSmith\n\nIntroduction:\nThe purpose of this research report is to provide a comprehensive understanding of LangSmith, a developer platform designed to facilitate the development and management of Language Model applications (LLMs). Through an analysis of the gathered research, this report aims to answer the question: "What is LangSmith?"\n\nResearch Findings:\n\n1. LangSmith Overview:\nLangSmith is a unified platform that helps developers trace, evaluate, and monitor LLM applications and intelligent agents. It aims to simplify the process of moving from prototype to production by providing features such as tracing runs, testing prompts or answers, and exporting datasets and runs for further analysis. LangSmith offers comprehensive visibility into the chain sequence of calls, real-time insights, and observability features to monitor LLM applications. It emphasizes best practices and offers useful tools and resources for developers working with LLMs.\n\n2. Key Features of LangSmith:\nLangSmith offers several key features to assist developers in building and managing LLM applications. These include:\n- Tracing and evaluating the behavior of LLM applications.\n- Debugging and experimentation capabilities.\n- Sharing work with others.\n- Creating datasets for testing and evaluation.\n- Evaluating models based on created datasets.\n- Monitoring the behavior and performance of LLM applications.\n- Comprehensive visibility into the entire chain sequence of calls.\n\n3. LangSmith\'s Integration with LangChain:\nLangSmith seamlessly integrates with LangChain, a library for prototyping LLM applications. This integration allows developers to leverage the composability of LangChain and build applications with large language models effectively. LangChain supports features such as memory, custom datasets, and more.\n\n4. Potential Alternatives to LangSmith:\nBased on the research findings, several potential alternatives to LangSmith have been identified. These include:\n- LangChain: An open-source framework for building applications with large language models through composability.\n- GradientJ: A platform to build, orchestrate, and manage complex LLM applications at scale.\n- LLMOps.Space: A community and resource hub focused on deploying LLMs into production.\n- Vellum: A development platform aimed at production LLM applications, providing tools for monitoring, version control, and testing datasets.\n- Llama2: An open-source large language model from Meta that can be fine-tuned and deployed.\n- Openlayer: A platform focused on ML model testing, monitoring, and improvement.\n- Backengine: A platform that allows creating and deploying backend APIs using natural language descriptions.\n- QueryVary: A platform for systematically designing and refining prompts for LLMs.\n\nConclusion:\nIn conclusion, LangSmith is a developer platform designed to simplify the development and management of Language Model applications (LLMs). It provides developers with tools for tracing, testing, evaluating, and monitoring LLM applications, along with comprehensive visibility and real-time insights. LangSmith aims to empower developers and handle the complexity of LLM applications effectively. By integrating seamlessly with LangChain, it offers enhanced capabilities for building applications with large language models. While LangSmith is a prominent platform, developers may also consider other alternatives such as LangChain, GradientJ, LLMOps.Space, Vellum, and more, depending on their specific requirements.']
In [ ]: