diff --git a/libs/partners/cohere/docs/multi_hop_agent.ipynb b/libs/partners/cohere/docs/multi_hop_agent.ipynb
new file mode 100644
index 0000000000000..a31e9d030f1c0
--- /dev/null
+++ b/libs/partners/cohere/docs/multi_hop_agent.ipynb
@@ -0,0 +1,408 @@
+{
+ "cells": [
+ {
+ "cell_type": "raw",
+ "metadata": {},
+ "source": [
+ "---\n",
+ "sidebar_position: 0\n",
+ "---"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "# Cohere Tools\n",
+ "\n",
+ "The following notebook goes over how to use the Cohere tools agent:"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Prerequisites for this notebook:"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 1,
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "Requirement already satisfied: langchain-cohere in /Users/beatrix/Repos/langchain-1/.venv/lib/python3.11/site-packages (0.1.0rc0)\n",
+ "Requirement already satisfied: cohere<6.0.0,>=5.1.1 in /Users/beatrix/Repos/langchain-1/.venv/lib/python3.11/site-packages (from langchain-cohere) (5.1.2)\n",
+ "Requirement already satisfied: langchain-core<0.2.0,>=0.1.32 in /Users/beatrix/Repos/langchain-1/.venv/lib/python3.11/site-packages (from langchain-cohere) (0.1.33)\n",
+ "Requirement already satisfied: httpx>=0.21.2 in /Users/beatrix/Repos/langchain-1/.venv/lib/python3.11/site-packages (from cohere<6.0.0,>=5.1.1->langchain-cohere) (0.27.0)\n",
+ "Requirement already satisfied: pydantic>=1.9.2 in /Users/beatrix/Repos/langchain-1/.venv/lib/python3.11/site-packages (from cohere<6.0.0,>=5.1.1->langchain-cohere) (2.6.4)\n",
+ "Requirement already satisfied: typing_extensions>=4.0.0 in /Users/beatrix/Repos/langchain-1/.venv/lib/python3.11/site-packages (from cohere<6.0.0,>=5.1.1->langchain-cohere) (4.10.0)\n",
+ "Requirement already satisfied: PyYAML>=5.3 in /Users/beatrix/Repos/langchain-1/.venv/lib/python3.11/site-packages (from langchain-core<0.2.0,>=0.1.32->langchain-cohere) (6.0.1)\n",
+ "Requirement already satisfied: anyio<5,>=3 in /Users/beatrix/Repos/langchain-1/.venv/lib/python3.11/site-packages (from langchain-core<0.2.0,>=0.1.32->langchain-cohere) (4.3.0)\n",
+ "Requirement already satisfied: jsonpatch<2.0,>=1.33 in /Users/beatrix/Repos/langchain-1/.venv/lib/python3.11/site-packages (from langchain-core<0.2.0,>=0.1.32->langchain-cohere) (1.33)\n",
+ "Requirement already satisfied: langsmith<0.2.0,>=0.1.0 in /Users/beatrix/Repos/langchain-1/.venv/lib/python3.11/site-packages (from langchain-core<0.2.0,>=0.1.32->langchain-cohere) (0.1.31)\n",
+ "Requirement already satisfied: packaging<24.0,>=23.2 in /Users/beatrix/Repos/langchain-1/.venv/lib/python3.11/site-packages (from langchain-core<0.2.0,>=0.1.32->langchain-cohere) (23.2)\n",
+ "Requirement already satisfied: requests<3,>=2 in /Users/beatrix/Repos/langchain-1/.venv/lib/python3.11/site-packages (from langchain-core<0.2.0,>=0.1.32->langchain-cohere) (2.31.0)\n",
+ "Requirement already satisfied: tenacity<9.0.0,>=8.1.0 in /Users/beatrix/Repos/langchain-1/.venv/lib/python3.11/site-packages (from langchain-core<0.2.0,>=0.1.32->langchain-cohere) (8.2.3)\n",
+ "Requirement already satisfied: idna>=2.8 in /Users/beatrix/Repos/langchain-1/.venv/lib/python3.11/site-packages (from anyio<5,>=3->langchain-core<0.2.0,>=0.1.32->langchain-cohere) (3.6)\n",
+ "Requirement already satisfied: sniffio>=1.1 in /Users/beatrix/Repos/langchain-1/.venv/lib/python3.11/site-packages (from anyio<5,>=3->langchain-core<0.2.0,>=0.1.32->langchain-cohere) (1.3.1)\n",
+ "Requirement already satisfied: certifi in /Users/beatrix/Repos/langchain-1/.venv/lib/python3.11/site-packages (from httpx>=0.21.2->cohere<6.0.0,>=5.1.1->langchain-cohere) (2024.2.2)\n",
+ "Requirement already satisfied: httpcore==1.* in /Users/beatrix/Repos/langchain-1/.venv/lib/python3.11/site-packages (from httpx>=0.21.2->cohere<6.0.0,>=5.1.1->langchain-cohere) (1.0.4)\n",
+ "Requirement already satisfied: h11<0.15,>=0.13 in /Users/beatrix/Repos/langchain-1/.venv/lib/python3.11/site-packages (from httpcore==1.*->httpx>=0.21.2->cohere<6.0.0,>=5.1.1->langchain-cohere) (0.14.0)\n",
+ "Requirement already satisfied: jsonpointer>=1.9 in /Users/beatrix/Repos/langchain-1/.venv/lib/python3.11/site-packages (from jsonpatch<2.0,>=1.33->langchain-core<0.2.0,>=0.1.32->langchain-cohere) (2.4)\n",
+ "Requirement already satisfied: orjson<4.0.0,>=3.9.14 in /Users/beatrix/Repos/langchain-1/.venv/lib/python3.11/site-packages (from langsmith<0.2.0,>=0.1.0->langchain-core<0.2.0,>=0.1.32->langchain-cohere) (3.9.15)\n",
+ "Requirement already satisfied: annotated-types>=0.4.0 in /Users/beatrix/Repos/langchain-1/.venv/lib/python3.11/site-packages (from pydantic>=1.9.2->cohere<6.0.0,>=5.1.1->langchain-cohere) (0.6.0)\n",
+ "Requirement already satisfied: pydantic-core==2.16.3 in /Users/beatrix/Repos/langchain-1/.venv/lib/python3.11/site-packages (from pydantic>=1.9.2->cohere<6.0.0,>=5.1.1->langchain-cohere) (2.16.3)\n",
+ "Requirement already satisfied: charset-normalizer<4,>=2 in /Users/beatrix/Repos/langchain-1/.venv/lib/python3.11/site-packages (from requests<3,>=2->langchain-core<0.2.0,>=0.1.32->langchain-cohere) (3.3.2)\n",
+ "Requirement already satisfied: urllib3<3,>=1.21.1 in /Users/beatrix/Repos/langchain-1/.venv/lib/python3.11/site-packages (from requests<3,>=2->langchain-core<0.2.0,>=0.1.32->langchain-cohere) (2.2.1)\n",
+ "Requirement already satisfied: wikipedia in /Users/beatrix/Repos/langchain-1/.venv/lib/python3.11/site-packages (1.4.0)\n",
+ "Requirement already satisfied: beautifulsoup4 in /Users/beatrix/Repos/langchain-1/.venv/lib/python3.11/site-packages (from wikipedia) (4.12.3)\n",
+ "Requirement already satisfied: requests<3.0.0,>=2.0.0 in /Users/beatrix/Repos/langchain-1/.venv/lib/python3.11/site-packages (from wikipedia) (2.31.0)\n",
+ "Requirement already satisfied: charset-normalizer<4,>=2 in /Users/beatrix/Repos/langchain-1/.venv/lib/python3.11/site-packages (from requests<3.0.0,>=2.0.0->wikipedia) (3.3.2)\n",
+ "Requirement already satisfied: idna<4,>=2.5 in /Users/beatrix/Repos/langchain-1/.venv/lib/python3.11/site-packages (from requests<3.0.0,>=2.0.0->wikipedia) (3.6)\n",
+ "Requirement already satisfied: urllib3<3,>=1.21.1 in /Users/beatrix/Repos/langchain-1/.venv/lib/python3.11/site-packages (from requests<3.0.0,>=2.0.0->wikipedia) (2.2.1)\n",
+ "Requirement already satisfied: certifi>=2017.4.17 in /Users/beatrix/Repos/langchain-1/.venv/lib/python3.11/site-packages (from requests<3.0.0,>=2.0.0->wikipedia) (2024.2.2)\n",
+ "Requirement already satisfied: soupsieve>1.2 in /Users/beatrix/Repos/langchain-1/.venv/lib/python3.11/site-packages (from beautifulsoup4->wikipedia) (2.5)\n",
+ "Note: you may need to restart the kernel to use updated packages.\n"
+ ]
+ }
+ ],
+ "source": [
+ "# install package\n",
+ "!pip install -U langchain-cohere\n",
+ "%pip install wikipedia"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 2,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "from langchain.agents import AgentExecutor\n",
+ "from langchain_cohere.chat_models import ChatCohere\n",
+ "from langchain_cohere.multi_hop.agent import create_cohere_multi_hop_agent\n",
+ "from langchain.retrievers import WikipediaRetriever\n",
+ "from langchain.tools.retriever import create_retriever_tool\n",
+ "from langchain_core.prompts import ChatPromptTemplate"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Next we create the prompt template and cohere model"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 3,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# Create the prompt\n",
+ "prompt = ChatPromptTemplate.from_template(\n",
+ " \"Write all output in capital letters. {input}\"\n",
+ ")\n",
+ "\n",
+ "# Create the Cohere chat model\n",
+ "chat = ChatCohere(cohere_api_key=\"API_KEY\", model=\"command-r\")"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "In this example we use a Wikipedia retrieval tool "
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 4,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "retriever = WikipediaRetriever()\n",
+ "retriever_tool = create_retriever_tool(\n",
+ " retriever,\n",
+ " \"wikipedia\",\n",
+ " \"Search for information on Wikipedia\",\n",
+ ")"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Next, create the cohere tool agent and call with the input"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 5,
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "\n",
+ "\n",
+ "\u001b[1m> Entering new AgentExecutor chain...\u001b[0m\n",
+ "\u001b[32;1m\u001b[1;3mPlan: I will first search for who the second person to walk on the moon was, then I will search for that person's mother's hometown.\n",
+ "Action: ```json\n",
+ "[\n",
+ " {\n",
+ " \"tool_name\": \"wikipedia\",\n",
+ " \"parameters\": {\n",
+ " \"query\": \"second man to walk on the moon\"\n",
+ " }\n",
+ " }\n",
+ "]\n",
+ "```\u001b[0m\u001b[36;1m\u001b[1;3mWalk the Moon (stylized as WALK THE MOON) is an American pop rock band based in Cincinnati, Ohio. Lead singer Nicholas Petricca started the band in 2006, while a student at Kenyon College, deriving the band's name from the song \"Walking on the Moon\" by The Police. Although the band is best known for their most successful hit single to date \"Shut Up and Dance\", other notable songs include \"Anna Sun\" and \"One Foot\".\n",
+ "Walk the Moon has cited Talking Heads as influences. The band's use of 1980s musical mainstays, such as keyboard and synthesizer, is also notable.\n",
+ "\n",
+ "\n",
+ "== History ==\n",
+ "\n",
+ "\n",
+ "=== 2010–2011: Beginning, Anna Sun and i Want! i Want! ===\n",
+ "\n",
+ "The group independently released their debut studio album, I Want! I Want!, in November 2010, receiving airplay for the track \"Anna Sun\" on multiple alternative radio stations. Along with the success of \"Anna Sun\", Alt Nation named them a band you need to know for the summer of 2012. Influential music blog Neon Gold helped to break the band in January 2011, calling \"Anna Sun\", \"the kind of stuff British A&R dreams, and major label bidding wars, are made of.\" In February 2011, Walk the Moon signed to RCA Records.\n",
+ "In 2011, the band members began to paint their faces for live performances and they would bring enough paint to share with audience members. They have claimed it has become a “live tradition”. Bonnaroo’s camera crew documented the painting process in a short video from the 2011 festival. The band played at the Sasquatch Music Festival and Firefly Music Festival. In these years, they were known for their energetic performances and tireless touring schedule.\n",
+ "Before the release of their self-titled album, Walk the Moon joined many other performers at the Music Midtown festival and performed on the Great Southeast Music Hall Stage in Atlanta, Georgia in September 2011. In spring 2011, the band went on a short tour with the west coast band, Grouplove, as well as supporting Panic! at the Disco and Weezer on select dates. The band played on the main stage at the 20th Anniversary of Lollapalooza and also supported Local Natives in an Official Lollaplooza Aftershow at Lincoln Hall.\n",
+ "The band recorded i Want! i Want! with Chris Schmidt and Ben Cochran at Soap Floats Recording Studio in their hometown of Cincinnati, Ohio and then self-released it. The lead single from the album, \"Anna Sun\", became a surprise hit in the summer of 2011 following an endorsement by the Esquire article \"30 Summer Songs Every Man Should Listen To\". The song was written by Petricca and New York songwriter Nick Lerangis as their time at Kenyon College came to an end. \"It's about college, about maintaining that little bit of being a kid,\" Petricca said. \"Don't be afraid to play.\" The song was named after one of their favorite teachers. It was named song of the summer by MTV and Seventeen Mag, and one of the top songs of the year by Amazon. It has been officially remixed by Fool's Gold and received a Trouble Productions remix by Albert Hammond Jr. Anna Sun rose to the number one spot on Alt. Nation on Sirius XM Radio. \"Anna Sun\" was added to the video rotation of American Eagle Outfitters stores in May 2011. It was featured on the hit TV show Vampire Diaries in the first episode of season three. It was also the free single of the week on iTunes for the week of May 15.\n",
+ "Filmed in 2011 in Cincinnati's Over-the-Rhine neighborhood, the \"Anna Sun\" music video was released to coincide with the album. The video was shot on-location at the Cincinnati Mockbee building, as well as at a city park. It was directed and produced by Patrick Meier of the Cincinnati company, Contrast Productions, and features original choreography from Kim Popa of PONES Inc., as well as a cast full of the band's friends and locals from Cincinnati. MTV Hive calls the video a \"hilariously choreographed, neon-colored and awesomely shot in one take\" production.\n",
+ "\n",
+ "\n",
+ "=== 2012–2013: Walk the Moon and Tightrope EP ===\n",
+ "\n",
+ "The band's self-titled major label debut Walk t\n",
+ "\n",
+ "\"Man on the Moon\" is a song by American alternative rock band R.E.M., released in November 1992 as the second single from their eighth album, Automatic for the People (1992). The lyrics were written by lead singer Michael Stipe, and the music by drummer Bill Berry and guitarist Peter Buck. The song was well received by critics and reached number 30 on the US Billboard Hot 100, number 17 on the US Cash Box Top 100, number 18 on the UK Singles Chart, and number one in Iceland. It remains one of R.E.M.'s most popular songs and was included on the compilations In Time: The Best of R.E.M. 1988–2003 and Part Lies, Part Heart, Part Truth, Part Garbage 1982–2011.\n",
+ "\"Man on the Moon\" is a tribute to comedian Andy Kaufman, with numerous references to his career including his Elvis impersonation, wrestling, and the film My Breakfast with Blassie. The song's title and chorus refer to Moon landing conspiracy theories, as an oblique allusion to rumors that Kaufman's death in 1984 was faked. The song gave its name to Miloš Forman's Kaufman biopic Man on the Moon (1999), and features prominently in the film's soundtrack.\n",
+ "\n",
+ "\n",
+ "== Composition ==\n",
+ "\"Man on the Moon\" is a mid-tempo country-rock song following a verse-chorus structure with an added pre-chorus and an instrumental bridge following the second and third choruses. The song has six lines in the first verse but only four in the second and third verses.An early instrumental demo of the song was known to the band as \"C to D Slide\". Guitarist Peter Buck has explained how the music came together: \"'Man on the Moon' was something that Bill [Berry] had, this one chord change that he came in with, which was C to D like the verse of the song, and he said: 'I don't know what to do with that.' I used to finish some of Bill's things ... he would come up with the riffs, but I would be the finish guy for that. I sat down and came up with the chorus, the bridges, and so forth. I remember we showed it to Mike and Michael when they came in later; definitely we had the song finished. I think Bill played bass and I played guitar; we kept going around with it. I think we might have played some mandolin on it in the rehearsal studio.\"Michael Stipe explained in an interview with Charlie Rose how the lyric was written independently of the music, which had no prior association with the song's eventual lyrical content regarding Kaufman. Stipe recounted the other R.E.M. members had written and performed the music of the song and recorded it along with the rest of the Automatic for the People album during studio sessions in Seattle. As of the final week of the recording sessions, Stipe was still struggling to write the lyric, and the others continued to plead with him to finish it. Stipe attempted to argue the track should be an instrumental, but his bandmates were insistent. Stipe listened to the track on a walk around Seattle on his Walkman cassette player and was inspired to write about Andy Kaufman. After Stipe went back to the studio to complete the vocal track, the track was mixed that night and sent out the following day to be mastered.\n",
+ "\n",
+ "\n",
+ "== Lyric ==\n",
+ "The song's lyric does not tell a conventional story and instead forms a collection of cultural references, images and ideas. There are repeated mentions of Andy Kaufman, including references to his Elvis impersonation and work with wrestlers Fred Blassie and Jerry Lawler. The song also invokes the conspiracy theories surrounding the Moon landing and Elvis Presley's death as an indirect nod to the persistent rumors that Kaufman faked his own death. Speaking in 2017 to the NME, Mike Mills explained that the perceived ambiguity of Kaufman's legacy, including questions of whether he was a comedian or a performance artist, and whether his work was funny or irritating, was a way to frame other questions about life within the song:\n",
+ "\n",
+ "He's the perfect ghost to lead you through this tour of questioning things. Did the moon landing really happen? Is Elvis really dead? He was ki\n",
+ "\n",
+ "As part of the Apollo program by NASA, 24 astronauts flew nine missions to the Moon between December 1968 and December 1972. During six successful two-man landing missions, twelve men walked on the lunar surface, six of whom drove Lunar Roving Vehicles as part of the last three missions. Three men have been to the Moon twice, one orbited once and took a circumlunar trajectory the second time, while the other two landed once apiece. Apart from these 24 men, no human being has gone beyond low Earth orbit. No woman has been to the Moon, but a number of non-human animals have circled or orbited it, including two tortoises, several turtles, and five mice.\n",
+ "Apollo missions 8 and 10–17 were the nine crewed missions to the Moon. Apollo 4–6 and AS-201 and AS-202 were uncrewed, while AS-203 is considered a test flight. The Apollo program included three other crewed missions: Apollo 1 (AS-204) did not launch and its crew died in a ground-based capsule fire, while Apollo 7 and Apollo 9 were low Earth orbit missions that only tested spacecraft components and docking maneuvers. Apollo missions 18, 19, and 20 were canceled. Twelve astronauts later flew unused Apollo command modules in the Apollo Applications Program's Skylab and Apollo–Soyuz Test Project. Of the 24 astronauts who flew to the Moon, two went on to command a Skylab mission, one commanded Apollo–Soyuz, one flew as commander for Approach and Landing Tests of the Space Shuttle, and two commanded orbital Space Shuttle missions.\n",
+ "\n",
+ "\n",
+ "== Prime crew members ==\n",
+ "NASA's Director of Flight Crew Operations during the Gemini and Apollo programs was Donald K. \"Deke\" Slayton, one of the original Mercury Seven astronauts, who was medically grounded in September 1962 due to a minor cardiac arrhythmia – paroxysmal atrial fibrillation. Slayton was responsible for making all Gemini and Apollo crew assignments. In March 1972, Slayton was restored to flight status, and flew on the 1975 Apollo–Soyuz Test Project mission.\n",
+ "The prime crew members selected for actual missions are here grouped by their NASA astronaut selection groups, and within each group in the order selected for flight. Two versions of the Apollo Command/Service Module (CSM) spacecraft were developed: Block I, intended for preliminary low Earth orbit testing; and Block II, redesigned for the lunar landing. The Block I crew position titles were Command Pilot, Senior Pilot (second seat), and Pilot (third seat). The corresponding Block II titles were: Commander, Command Module Pilot, and Lunar Module Pilot. The second seat pilot was given secondary responsibility for celestial navigation to keep the CSM's guidance computer accurately calibrated with the spacecraft's true position, and the third seat pilot served as a flight engineer, monitoring the health of the spacecraft systems.\n",
+ "\n",
+ "\n",
+ "== Apollo astronauts by their dates of selection by NASA ==\n",
+ "\n",
+ "\n",
+ "=== 1959 ===\n",
+ "Virgil I. \"Gus\" Grissom began his career at NASA in 1959. In 1966, he was selected as Command Pilot for the first crewed Apollo mission, a low Earth orbit test. This mission ended a month before its scheduled launch, when a cabin fire on the launch pad killed Grissom, Ed White and Roger Chaffee on January 27, 1967.\n",
+ "Walter M. Schirra Jr. also began his NASA career in 1959. He was selected in October 1968 as Command Pilot for Apollo 7, an 11-day, low Earth orbit shakedown test of the three-man Apollo Command/Service Module and the first crewed launch for the Apollo project.\n",
+ "Alan B. Shepard Jr. – America's first man in space on Freedom 7 was originally selected to command Gemini 3, but was medically grounded for the duration of Gemini due to Ménière's disease and assisted Slayton in Flight Operations. After corrective surgery, Shepard was restored to flight status and commanded Apollo 14, the third successful Moon landing mission.\n",
+ "\n",
+ "\n",
+ "=== 1962 ===\n",
+ "\n",
+ "All of these astronauts flew on Gemini, and except for White, each commanded one Gemini and one Apollo mission:\n",
+ "\n",
+ "Edward H. White II – Second-seat \u001b[0m\u001b[32;1m\u001b[1;3mReflection: I have found that the second person to walk on the moon was Alan Shepard Jr.. I will now search for Alan Shepard Jr.'s mother's hometown.\n",
+ "Action: ```json\n",
+ "[\n",
+ " {\n",
+ " \"tool_name\": \"wikipedia\",\n",
+ " \"parameters\": {\n",
+ " \"query\": \"Alan Shepard Jr. mother hometown\"\n",
+ " }\n",
+ " }\n",
+ "]\n",
+ "```\u001b[0m\u001b[36;1m\u001b[1;3mAlan Eugene Jackson (born October 17, 1958) is an American singer-songwriter. He is known for performing a style widely regarded as \"neotraditional country\", as well as penning many of his own songs. Jackson has recorded 21 studio albums, including two Christmas albums, and two gospel albums, as well as released three greatest-hits albums.\n",
+ "Jackson is one of the best-selling music artists of all time, having sold over 75 million records worldwide, with 44 million sold in the United States alone. He has had 66 songs appear on the Billboard Hot Country Singles & Tracks chart; of the 66 titles, and six featured singles, 38 have reached the top five and 35 have claimed the number one spot. Out of 15 titles to reach the Billboard Top Country Albums chart, nine have been certified multi-platinum. He is the recipient of two Grammy Awards, 16 CMA Awards, 17 ACM Awards and nominee of multiple other awards. He is a member of the Grand Ole Opry, and was inducted into the Georgia Music Hall of Fame in 2001. He was inducted into the Country Music Hall of Fame in 2017 by Loretta Lynn and into the Nashville Songwriters Hall of Fame in 2018.\n",
+ "\n",
+ "\n",
+ "== Early life ==\n",
+ "Jackson was born to Joseph Eugene \"Daddy Gene\" Jackson (1927–2000) and Ruth Musick \"Mama Ruth\" Jackson (1930–2017) in Newnan, Georgia, and has four older sisters. He and his immediate family lived in a small home built around his grandfather's old toolshed. The family is primarily of English descent. His mother lived in the home until her death on January 7, 2017. He began writing music in 1983.Growing up, Jackson listened primarily to gospel music, until a friend introduced him to Gene Watson, John Anderson, and Hank Williams Jr. Jackson attended the local Elm Street Elementary and Newnan High School, and joined the band Dixie Steel after graduation. When he was 27, Jackson and his wife of six years, Denise, moved from Newnan to Nashville, Tennessee, where he hoped to pursue music full-time. In 1987, Jackson cut a pre-debut demo album titled New Traditional at Doc's Place in Hendersonville, Tennessee, but it is extremely rare and was released only in Japan.\n",
+ "\n",
+ "\n",
+ "== Career ==\n",
+ "In Tennessee, Jackson got his first job in The Nashville Network's mailroom. His wife Denise was a flight attendant. While working, she came in contact with Glen Campbell and requested advice for her husband. Campbell handed her his business card of his manager and told her to call, which helped jumpstart his career. Jackson eventually signed with Arista, and in 1989, he became the first artist signed to the newly formed Arista Nashville branch of Arista Records. Arista released Jackson's debut single, \"Blue Blooded Woman\", in late 1989. Although the song failed to reach top 40 on Hot Country Songs, he reached number three by early 1990 with \"Here in the Real World\". This song served as the title track to his debut studio album, Here in the Real World, which also included two more top five hits (\"Wanted\" and \"Chasin' That Neon Rainbow\") and his first number one, \"I'd Love You All Over Again\". Don't Rock the Jukebox was the title of Jackson's second album. Released in 1991, it included four number-one singles: the title track, \"Someday\", \"Dallas\" and \"Love's Got a Hold on You\", and the number three \"Midnight in Montgomery\". Jackson also co-wrote several songs on Randy Travis' 1991 album High Lonesome.A Lot About Livin' (And a Little 'bout Love), his third album, accounted for the number one hits \"She's Got the Rhythm (And I Got the Blues)\" (which Randy Travis co-wrote) and \"Chattahoochee\", plus the top five hits \"Tonight I Climbed the Wall\", \"Mercury Blues\" and \"(Who Says) You Can't Have It All\". \"Chattahoochee\" also won him the 1994 Country Music Association (CMA) awards for Single and Song of the Year. In 1994, Jackson left his management company, Ten Ten Management, which had overseen his career up to that point, and switched to Gary Overton. His fourth album was titled Who I Am, and it contained four number one hit\n",
+ "\n",
+ "Here is a list of characters appearing on the 1978–1991 American television series Dallas. During its 14 seasons on air, the show featured 21 regular cast members, portraying twenty characters (as the character of Miss Ellie was recast for season eight). Additionally, hundreds of guest actors portrayed supporting characters; this list includes the most noteworthy.\n",
+ "\n",
+ "\n",
+ "== Main cast timeline ==\n",
+ "Cast notes\n",
+ "\n",
+ "\n",
+ "== Supporting characters ==\n",
+ "\n",
+ "\n",
+ "=== Ewing relatives ===\n",
+ "\n",
+ "\n",
+ "==== Gary Ewing ====\n",
+ "\n",
+ "Garrison Arthur \"Gary\" Ewing (David Ackroyd in season 2, Ted Shackelford thereafter) was the middle son of Jock (Jim Davis) and Miss Ellie Ewing (Barbara Bel Geddes), husband of Valene (Joan Van Ark) and father of Lucy Ewing (Charlene Tilton). He appeared occasionally between season 2 and season 6, once in season 9, and the series finale in season 14. The character made 11 appearances on the show, Ackroyd for the first two and Shackelford for the remaining nine.\n",
+ "Gary was the middle child, being born after J.R. (Larry Hagman) and before Bobby (Patrick Duffy). He was raised while Jock was at war, and displayed traits of his mother's family, the Southworths, which meant that Jock and J.R. saw him as a weak link. At 17, to try and escape his family, Gary ran away and married 15-year-old Valene and got her pregnant, which resulted in the birth of their daughter Lucy. Valene eventually forced Gary to introduce her to his family, and upon his return Jock and Miss Ellie gave him a home and a job on Southfork Ranch. J.R., who disliked Valene and resented Gary's presence, harassed Gary to the point of alcoholism and forced him off the ranch. Gary disappeared and wound up working as a waiter in a Las Vegas hotel, where he encountered Bobby and his wife Pam (Victoria Principal) in 1978.\n",
+ "Bobby and Pam convinced Gary to return to Southfork, reconciling with Lucy, who engineered a meeting between him and Valene. For a brief while, the three cohabited at Southfork as a family under Jock and Miss Ellie's eyes, but Gary soon felt trapped by Jock's expectations and J.R.'s resentment. Realising that this would send him back to alcoholism, Gary abandoned his family and Southfork. Valene followed, and the two eventually reconciled again and married in season 3. As a gift to the newlyweds, Miss Ellie bought them a house in California, where Gary and Valene settled after their honeymoon.\n",
+ "Gary remained in California, free from the pressures of his family, although he returned to Dallas on several occasions: to visit J.R. in hospital after Kristin Shepard (Mary Crosby) tried to kill him; for Lucy's wedding to Mitch Cooper (Leigh McCloskey); to support Miss Ellie after the death of his father, Jock; and for Bobby's \"funeral\" during the dream season. Following this, Gary didn't return to Dallas again, although he appeared in an alternate reality in which J.R. had never been born during the series finale: without J.R. to intimidate him, Gary became the eldest son and became a successful divorce lawyer, after inheriting Ewing Oil and running it into the ground. He still met and started a relationship with Valene, although they did not meet for the first time until their middle age (and, subsequently, did not have Lucy). The alternate reality also suggested that, regardless of J.R.'s interference, Gary and Valene were always destined to end up together.\n",
+ "Gary and Valene's backstories and lives in California were the basis of Dallas spin-off series Knots Landing. The couple also appeared for brief story arcs in the revival series.\n",
+ "\n",
+ "\n",
+ "==== Valene Clements Ewing ====\n",
+ "\n",
+ "Valene \"Val\" Ewing (also Clements, Gibson and Waleska; credited as Valene Wallace in the series finale) was the wife of Gary Ewing (David Ackroyd/Ted Shackelford) and mother of Lucy Ewing (Charlene Tilton). She appeared occasionally between season 2 and season 5, and returned in the series finale in season 14. Van Ark appeared in 8 episodes overall, and featured briefly in uncredited archive footage during season 12.\n",
+ "At 15\n",
+ "\n",
+ "\"Kill Ari (Part I)\" and \"Kill Ari (Part II)\" are the first two episodes of the third season of the American police procedural drama NCIS, and the 47th and 48th episodes overall. They originally aired on CBS in the United States on September 20 and 27, 2005. Both episodes are written by Donald Bellisario, the show's creator and executive producer at the time. Part I, directed by Dennis Smith, was seen live by 15.48 million viewers, while Part II, directed by James Whitmore, Jr., was seen live by 15.09 million viewers.The \"Kill Ari\" story arc centers on Gibbs' hunt for Ari Haswari, who shot and killed Special Agent Kate Todd in the second-season finale of NCIS. It also introduces two new main characters to the show—Mossad Officer Ziva David and NCIS Director Jenny Shepard. Due to these changes in the cast, Bellisario labeled the third season as \"the season of change\".\n",
+ "\n",
+ "\n",
+ "== Plot ==\n",
+ "\n",
+ "\n",
+ "=== Part I ===\n",
+ "The episode opens with a recap of the second season's finale, \"Twilight\": as the NCIS team by Leroy Jethro Gibbs (Mark Harmon) engage in a gunfight against Ari Haswari's terrorist cell, Ari (Rudolf Martin), identified as a rogue terrorist, attempts to kill various NCIS agents including Tim McGee (Sean Murray) before Ari decides to fatally shoot NCIS Agent Kate Todd (Sasha Alexander) with a long range sniper shot, killing her instantly with a horrified Gibbs and Tony DiNozzo (Michael Weatherly) witnessing Kate's death. In the aftermath of the murder, the team struggles to come to terms with her death while an enraged Gibbs seeks revenge against Ari. Shortly afterwards, Ari attacks again, firing at Abby in her lab. However, she survives physically unharmed.\n",
+ "Then NCIS Director Tom Morrow (Alan Dale) announces that he is leaving the agency after receiving a job offer from Homeland Security and introduces Jenny Shepard (Lauren Holly) as his replacement. It immediately becomes apparent that Gibbs was romantically involved with Shepard while working undercover with her years earlier, though she insists that she is now nothing more than his boss and will act accordingly. Gibbs clashes with Shepard, who believes that Ari Haswari was not the one responsible for firing the bullet that killed Agent Todd due to the fact that there's no physical evidence or proof of any kind linking him to the crime.\n",
+ "Ziva David (Cote de Pablo), Ari's Mossad control officer, arrives shortly afterwards, striking up a rapport with Tony. She sides with the director and further weakens Gibbs' case, claiming that Ari is completely innocent and offering evidence to support her assertion. However, Ziva's motives for defending Ari become ambiguous when she communicates with him without informing anyone in the NCIS office and her conversation indicates a personal connection to him.\n",
+ "Gibbs realizes that Ziva has contacted Ari and orders Tony to tail her. Ari later returns, taking Gerald Jackson (Pancho Demmings) hostage, though he quickly notifies Ducky to divert the team's attention away from Ziva and force Ducky into a meet.\n",
+ "The episode ends with Ducky approaching the pre-arranged meeting point, unaware that Ari has a sniper-rifle trained on him.\n",
+ "\n",
+ "\n",
+ "=== Part II ===\n",
+ "Gibbs' determination to kill Ari in revenge for Kate Todd's death increases despite the skepticism expressed by his superiors. Ducky, who is released unharmed shortly after his abduction, admits to Gibbs that he has begun to believe Ari's claims of innocence after listening to his defense, leaving Gibbs further enraged.\n",
+ "After tailing Ari's control officer, Ziva David, for much of the evening, Tony reports to Gibbs that she is communicating with Ari and smuggling a passport and money to him through an unknown woman (Gloria Votsis), presumably another Mossad officer. However, Ziva later approaches Tony and informs him that she was aware that he was following her the entire time. She also tells him that her younger sister Tali, who was \"sixteen and the best of us\", was killed in a Hamas suicide bombing, and that she kn\u001b[0m\u001b[32;1m\u001b[1;3mReflection: I could not find the information on Alan Shepard Jr.'s mother's hometown in this search, I will now search for Alan Shepard's mother's hometown.\n",
+ "Action: ```json\n",
+ "[\n",
+ " {\n",
+ " \"tool_name\": \"wikipedia\",\n",
+ " \"parameters\": {\n",
+ " \"query\": \"Alan Shepard mother's hometown\"\n",
+ " }\n",
+ " }\n",
+ "]\n",
+ "```\u001b[0m\u001b[36;1m\u001b[1;3mAlan Eugene Jackson (born October 17, 1958) is an American singer-songwriter. He is known for performing a style widely regarded as \"neotraditional country\", as well as penning many of his own songs. Jackson has recorded 21 studio albums, including two Christmas albums, and two gospel albums, as well as released three greatest-hits albums.\n",
+ "Jackson is one of the best-selling music artists of all time, having sold over 75 million records worldwide, with 44 million sold in the United States alone. He has had 66 songs appear on the Billboard Hot Country Singles & Tracks chart; of the 66 titles, and six featured singles, 38 have reached the top five and 35 have claimed the number one spot. Out of 15 titles to reach the Billboard Top Country Albums chart, nine have been certified multi-platinum. He is the recipient of two Grammy Awards, 16 CMA Awards, 17 ACM Awards and nominee of multiple other awards. He is a member of the Grand Ole Opry, and was inducted into the Georgia Music Hall of Fame in 2001. He was inducted into the Country Music Hall of Fame in 2017 by Loretta Lynn and into the Nashville Songwriters Hall of Fame in 2018.\n",
+ "\n",
+ "\n",
+ "== Early life ==\n",
+ "Jackson was born to Joseph Eugene \"Daddy Gene\" Jackson (1927–2000) and Ruth Musick \"Mama Ruth\" Jackson (1930–2017) in Newnan, Georgia, and has four older sisters. He and his immediate family lived in a small home built around his grandfather's old toolshed. The family is primarily of English descent. His mother lived in the home until her death on January 7, 2017. He began writing music in 1983.Growing up, Jackson listened primarily to gospel music, until a friend introduced him to Gene Watson, John Anderson, and Hank Williams Jr. Jackson attended the local Elm Street Elementary and Newnan High School, and joined the band Dixie Steel after graduation. When he was 27, Jackson and his wife of six years, Denise, moved from Newnan to Nashville, Tennessee, where he hoped to pursue music full-time. In 1987, Jackson cut a pre-debut demo album titled New Traditional at Doc's Place in Hendersonville, Tennessee, but it is extremely rare and was released only in Japan.\n",
+ "\n",
+ "\n",
+ "== Career ==\n",
+ "In Tennessee, Jackson got his first job in The Nashville Network's mailroom. His wife Denise was a flight attendant. While working, she came in contact with Glen Campbell and requested advice for her husband. Campbell handed her his business card of his manager and told her to call, which helped jumpstart his career. Jackson eventually signed with Arista, and in 1989, he became the first artist signed to the newly formed Arista Nashville branch of Arista Records. Arista released Jackson's debut single, \"Blue Blooded Woman\", in late 1989. Although the song failed to reach top 40 on Hot Country Songs, he reached number three by early 1990 with \"Here in the Real World\". This song served as the title track to his debut studio album, Here in the Real World, which also included two more top five hits (\"Wanted\" and \"Chasin' That Neon Rainbow\") and his first number one, \"I'd Love You All Over Again\". Don't Rock the Jukebox was the title of Jackson's second album. Released in 1991, it included four number-one singles: the title track, \"Someday\", \"Dallas\" and \"Love's Got a Hold on You\", and the number three \"Midnight in Montgomery\". Jackson also co-wrote several songs on Randy Travis' 1991 album High Lonesome.A Lot About Livin' (And a Little 'bout Love), his third album, accounted for the number one hits \"She's Got the Rhythm (And I Got the Blues)\" (which Randy Travis co-wrote) and \"Chattahoochee\", plus the top five hits \"Tonight I Climbed the Wall\", \"Mercury Blues\" and \"(Who Says) You Can't Have It All\". \"Chattahoochee\" also won him the 1994 Country Music Association (CMA) awards for Single and Song of the Year. In 1994, Jackson left his management company, Ten Ten Management, which had overseen his career up to that point, and switched to Gary Overton. His fourth album was titled Who I Am, and it contained four number one hit\n",
+ "\n",
+ "Mari Aldon (born Marija Aldona Pauliutė; 17 November 1925 – 31 October 2004) was a Lithuanian-born American actress.\n",
+ "\n",
+ "\n",
+ "== Early life ==\n",
+ "Mari Aldon was born in Tauragė, Lithuania. Her father Antanas Paulius was a policeman, mother Antanina (Antosė) Paulienė was a nurse. Father moved to America looking for a job. Soon after, when Mari was three years old, her mother also moved to Toronto, Canada with her daughter. There, she attended Givens Public School and Central High School. She studied ballet, drama, piano, and singing. Her early performances were noticed in Lithuanian newspapers of America. She had a sister.\n",
+ "\n",
+ "\n",
+ "== Career ==\n",
+ "Before Aldon began working in films, she acted for 11 months in a road company of A Streetcar Named Desire and danced with the Canadian Ballet. She also appeared on radio with Alan Young and on The Harold Peary Show.\n",
+ "After making her screen debut in a minor role in The Locket (1946) she gradually evolved to playing supporting or lead roles. Her most notable performance was starring opposite Gary Cooper in the 1951 Western Distant Drums. By the mid-1950s she was appearing either in B Pictures like the British thriller Mask of Dust (1954) or in supporting roles in more expensive films such as David Lean's Summertime (1955).After this point she worked largely in television, such as on the TV Western Wagon Train in 1959 as Freda Johnson in \"The Vivian Carter Story\" (S2E23) and in 1960 as Hester Millikan in \"The Jeremy Dow Story\" (S4E14). She guest-starred in a 1961 episode of Ichabod and Me.\n",
+ "\n",
+ "\n",
+ "== Personal life ==\n",
+ "Aldon married Tay Garnett in London, England on 13 August 1953. Their daughter, Tiela Aldon Garnett (later Daniels), was born in Los Angeles, California on 25 October 1955.On 17 January 1958, Aldon became a US citizen. In August 1970, Aldon filed for divorce from Garnett in Los Angeles, she was widowed seven years later. Aldon and Garnett had a ranch, near King Vidor in Paso Robles, California. Close relatives still live in her hometown of Tauragė, Lithuania, with whom she kept in touch.\n",
+ "\n",
+ "\n",
+ "== Death ==\n",
+ "Aldon died on 31 October 2004 in Las Vegas, aged 78, of cancer.\n",
+ "\n",
+ "\n",
+ "== Filmography ==\n",
+ "\n",
+ "\n",
+ "== References ==\n",
+ "\n",
+ "\n",
+ "== Bibliography ==\n",
+ "Aaker, Everett. George Raft: The Films. McFarland, 2013.\n",
+ "\n",
+ "\n",
+ "== External links ==\n",
+ "\n",
+ "Mari Aldon at IMDb\n",
+ "\n",
+ "Alan LaVern Bean (March 15, 1932 – May 26, 2018) was an American naval officer and aviator, aeronautical engineer, test pilot, NASA astronaut and painter. He was selected to become an astronaut by NASA in 1963 as part of Astronaut Group 3, and was the fourth person to walk on the Moon.\n",
+ "Before becoming an astronaut, Bean graduated with a Bachelor of Science degree in Aeronautical Engineering from University of Texas at Austin in 1955 and re-joined the U.S. Navy—he served as an enlisted member for a year after his high school graduation. He received his naval aviator wings in 1956 and served as a fighter pilot. In 1960, he graduated from the U.S. Naval Test Pilot School, flew as a test pilot and was The New Nine selection finalist in 1962.\n",
+ "He made his first flight into space aboard Apollo 12, the second crewed mission to land on the Moon, at age 37 in November 1969. He made his second and final flight into space on the Skylab 3 mission in 1973, the second crewed mission to the Skylab space station. After retiring from the United States Navy in 1975 and NASA in 1981, he pursued his interest in painting, depicting various space-related scenes and documenting his own experiences in space as well as those of his fellow Apollo program astronauts. He was the last living crew member of Apollo 12.\n",
+ "\n",
+ "\n",
+ "== Biography ==\n",
+ "\n",
+ "\n",
+ "=== Early life and education ===\n",
+ "Bean was born March 15, 1932, in Wheeler, the seat of Wheeler County in the northeastern Texas Panhandle, to parents Arnold Horace Bean and Frances Caroline Bean (née Murphy), who lived from 1908 to 1983, and 1906 to 1981, respectively. He considered Fort Worth his hometown. He was of Scottish descent. As a boy, he lived in Minden, the seat of Webster Parish in northwestern Louisiana, where his father worked for the U.S. Soil Conservation Service. Bean was a Boy Scout and he earned the rank of First Class. He graduated from R. L. Paschal High School in Fort Worth, Texas, in 1949. Following his high school graduation in 1949, Bean enlisted in the U.S. Naval Reserve.Bean received a Bachelor of Science degree in aeronautical engineering from the University of Texas at Austin in 1955, where he attended on a Naval Reserve Officers Training Corps (NROTC) scholarship. While at the university, he also joined the Delta Kappa Epsilon fraternity.\n",
+ "\n",
+ "\n",
+ "=== Military service ===\n",
+ "He was an Electronics Technician Striker at the NAS Dallas, Texas, until September 1950, when he was honorably discharged. In January 1955, Bean was commissioned a U.S. Navy ensign through the NROTC at the University of Texas at Austin, and attended flight training. After completing flight training in June 1956, he was assigned to Attack Squadron 44 (VA-44) at NAS Jacksonville, Florida, from 1956 to 1960, flying the F9F Cougar and A4D Skyhawk. After a four-year tour of duty, he attended the U.S. Naval Test Pilot School (USNTPS) at NAS Patuxent River, Maryland, where his instructor was his future Apollo 12 Commander, Pete Conrad, graduating in November 1960. Bean took art classes at St. Mary's College of Maryland during this tour, and flew as a test pilot on several types of naval aircraft. Following his assignment at USNTPS and aviation safety training with the University of Southern California (USC), he went through additional instruction with his old Attack Squadron 44, and was assigned to Navy Attack Squadron VA-172 at NAS Cecil Field, Florida, flying the A-4 Skyhawks, during which time he was selected as a NASA astronaut.Bean logged more than 7,145 hours of flying time, including 4,890 hours in jet aircraft.\n",
+ "\n",
+ "\n",
+ "=== NASA career ===\n",
+ "Bean was selected by NASA as part of Astronaut Group 3 in 1963 (after not being selected for Astronaut Group 2 the previous year). He was selected to be the backup command pilot for Gemini 10, but was unsuccessful in securing an early Apollo flight assignment. He was placed in the Apollo Applications Program in the interim. In that capacity, he was the first astronaut to dive in the Neutral Buoyancy Simu\u001b[0m\u001b[32;1m\u001b[1;3mRelevant Documents: 0,2\n",
+ "Cited Documents: 2\n",
+ "Answer: FORT WORTH WAS THE HOMETOWN OF THE MOTHER OF ALAN SHEPARD, THE SECOND PERSON TO WALK ON THE MOON.\n",
+ "Grounded answer: FORT WORTH WAS THE HOMETOWN OF THE MOTHER OF ALAN SHEPARD, THE SECOND PERSON TO WALK ON THE MOON.\u001b[0m\n",
+ "\n",
+ "\u001b[1m> Finished chain.\u001b[0m\n"
+ ]
+ },
+ {
+ "data": {
+ "text/plain": [
+ "{'input': 'What was the hometown of the mother of the second person to walk on the moon?',\n",
+ " 'output': 'FORT WORTH WAS THE HOMETOWN OF THE MOTHER OF ALAN SHEPARD, THE SECOND PERSON TO WALK ON THE MOON.'}"
+ ]
+ },
+ "execution_count": 5,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "agent = create_cohere_multi_hop_agent(\n",
+ " llm=chat,\n",
+ " tools=[retriever_tool],\n",
+ " prompt=prompt,\n",
+ ")\n",
+ "agent_executor = AgentExecutor(agent=agent, tools=[retriever_tool], verbose=True)\n",
+ "agent_executor.invoke({\"input\": \"What was the hometown of the mother of the second person to walk on the moon?\"})"
+ ]
+ }
+ ],
+ "metadata": {
+ "kernelspec": {
+ "display_name": "Python 3 (ipykernel)",
+ "language": "python",
+ "name": "python3"
+ },
+ "language_info": {
+ "codemirror_mode": {
+ "name": "ipython",
+ "version": 3
+ },
+ "file_extension": ".py",
+ "mimetype": "text/x-python",
+ "name": "python",
+ "nbconvert_exporter": "python",
+ "pygments_lexer": "ipython3",
+ "version": "3.11.7"
+ }
+ },
+ "nbformat": 4,
+ "nbformat_minor": 4
+}
diff --git a/libs/partners/cohere/langchain_cohere/__init__.py b/libs/partners/cohere/langchain_cohere/__init__.py
index 1f554a006e258..df2d50672edb9 100644
--- a/libs/partners/cohere/langchain_cohere/__init__.py
+++ b/libs/partners/cohere/langchain_cohere/__init__.py
@@ -1,5 +1,6 @@
from langchain_cohere.chat_models import ChatCohere
from langchain_cohere.embeddings import CohereEmbeddings
+from langchain_cohere.multi_hop.agent import create_cohere_multi_hop_agent
from langchain_cohere.rag_retrievers import CohereRagRetriever
from langchain_cohere.rerank import CohereRerank
@@ -9,4 +10,5 @@
"CohereEmbeddings",
"CohereRagRetriever",
"CohereRerank",
+ "create_cohere_multi_hop_agent",
]
diff --git a/libs/partners/cohere/langchain_cohere/multi_hop/__init__.py b/libs/partners/cohere/langchain_cohere/multi_hop/__init__.py
new file mode 100644
index 0000000000000..e69de29bb2d1d
diff --git a/libs/partners/cohere/langchain_cohere/multi_hop/agent.py b/libs/partners/cohere/langchain_cohere/multi_hop/agent.py
new file mode 100644
index 0000000000000..b1bdb4382c6c4
--- /dev/null
+++ b/libs/partners/cohere/langchain_cohere/multi_hop/agent.py
@@ -0,0 +1,261 @@
+import json
+import logging
+import re
+from typing import List, Sequence, Union
+
+from langchain_core.agents import AgentAction, AgentFinish
+from langchain_core.language_models import BaseLanguageModel
+from langchain_core.output_parsers import BaseOutputParser
+from langchain_core.prompts import PromptTemplate, BasePromptTemplate
+from langchain_core.prompts.chat import ChatPromptTemplate
+from langchain_core.runnables import Runnable, RunnablePassthrough
+from langchain_core.tools import BaseTool
+
+from langchain_cohere.multi_hop.prompt import multi_hop_prompt_template
+
+"""
+ Cohere multi-hop tool allows you to use multiple tools in parallel or
+ sequentially to complete your task. The agent uses a multi hop prompt by Cohere.
+ This prompt is experimental and subject to change.
+"""
+
+
+def create_cohere_multi_hop_agent(
+ llm: BaseLanguageModel,
+ tools: Sequence[BaseTool],
+ prompt: ChatPromptTemplate,
+) -> Runnable:
+ multi_hop_prompt = _render_prompt(tools=tools)
+ llm_with_tools = llm.bind(stop=["\nObservation:"])
+
+ agent = (
+ RunnablePassthrough.assign(
+ agent_scratchpad=lambda x: format_cohere_log_to_str(
+ x["intermediate_steps"],
+ ),
+ input=lambda x: prompt.format_messages(
+ input=x["input"], agent_scratchpad=x["intermediate_steps"]
+ ),
+ )
+ | multi_hop_prompt
+ | llm_with_tools
+ | CohereToolsMultiHopAgentOutputParser()
+ )
+ return agent
+
+
+def _render_prompt(tools: Sequence[BaseTool]) -> BasePromptTemplate:
+ return multi_hop_prompt_template.partial(
+ tools="\n".join([render_tool_description(t) for t in tools]),
+ )
+
+
+class CohereToolsMultiHopAgentOutputParser(
+ BaseOutputParser[Union[List[AgentAction], AgentFinish]]
+):
+ """Parses a message into agent actions/finish."""
+
+ @property
+ def _type(self) -> str:
+ return "cohere-tools-agent-output-parser"
+
+ def parse_jsonified_tool_use_generation(
+ self, tool_use_generation: str, tool_use_prefix: str
+ ) -> List[dict]:
+ """Parses model-generated jsonified actions.
+
+ Expects input of the form
+ "{tool_use_prefix}: ```json\n[{list of jsonified objects}]```"
+
+ outputs parsed list of jsonified objects.
+ """
+
+ def _extract_codeblocks_from_md(text: str) -> List[str]:
+ return re.findall(r"```([^`]*)```", text)
+
+ raw_generation = re.sub(f"^{tool_use_prefix} ", "", tool_use_generation)
+ code_block_sections = _extract_codeblocks_from_md(raw_generation)
+
+ if len(code_block_sections) != 1: # should have exactly 1 code block
+ raise ValueError(f"Action Parsing Failed: {tool_use_generation}")
+ # only json allowed:
+ assert code_block_sections[0].startswith(
+ "json\n"
+ ), f"Action Parsing Failed: {tool_use_generation}"
+
+ actions = json.loads(re.sub("^json\n", "", code_block_sections[0]))
+
+ if not isinstance(actions, list):
+ raise ValueError(f"Action Parsing Failed: {tool_use_generation}")
+
+ if len(actions):
+ if any(
+ not isinstance(action, dict) or "tool_name" not in action
+ for action in actions
+ ):
+ raise ValueError(f"Action Parsing Failed: {tool_use_generation}")
+ return actions
+
+ def parse_answer_with_prefixes(
+ self, completion: str, prefixes: dict[str, str]
+ ) -> dict[str, str]:
+ """parses string into key-value pairs,
+ according to patterns supplied in prefixes. Also strips.
+
+ if inputs are:
+ completion = "\nhello: sam\ngoodbye then: paul.",
+ prefixes = {"greeting": "hello:", "farewell": "goodbye then:"}
+
+ the expected returned result is:
+ {"greeting": "sam", "farewell": "paul."}
+
+ Args:
+ completion (str): text to split
+ prefixes (Dict[str, str]): a key-value dict of keys and patterns.
+ See example above
+
+ Returns:
+ Dict[str, str]: parsed result
+ """
+ # sort out prefixes
+ re_pat = "(" + "|".join([re.escape(p) for p in prefixes.values()]) + ")"
+ reverse_prefix_map = {v: k for k, v in prefixes.items()}
+ split = re.split(re_pat, completion)
+ split = split[1:]
+ parsed = {}
+ for prefix, value in zip(split[::2], split[1::2]):
+ if prefix in reverse_prefix_map: # if the prefix is a match
+ if (
+ reverse_prefix_map[prefix] not in parsed
+ ): # first occurrence of a prefix is kept, others discarded
+ parsed[reverse_prefix_map[prefix]] = value.strip()
+ return parsed
+
+ def parse_actions(self, generation: str) -> tuple[str, str, List[dict]]:
+ """Parse action selections from model output."""
+ plan = ""
+ actions = generation
+ try:
+ if "Plan: " in generation or "Reflection: " in generation:
+ # Model is trained to output a Plan or Reflection followed by an action.
+ # Use regex to extract the plan and action.
+ regex = (
+ r"^(Plan|Reflection)\s*\d*\s*:(.*?)"
+ + r"(Action\s*\d*\s*:\s*\d*\s*```json\n.*?```)"
+ )
+ action_match = re.search(regex, generation, re.DOTALL)
+ if not action_match:
+ raise ValueError(
+ f"Failed to parse multihop completion for input: {generation}"
+ )
+ plan = action_match.group(2).strip()
+ actions = action_match.group(3).strip()
+ else:
+ # Catch the case where model outputs only an action.
+ regex = r"^(Action\s*\d*\s*:\s*\d*\s*```json\n.*?```)"
+ action_match = re.search(regex, generation, re.DOTALL)
+ if not action_match:
+ raise ValueError(
+ f"Failed to parse multihop completion for input: {generation}"
+ )
+ actions = action_match.group(1).strip()
+ except Exception as e:
+ logging.error(
+ f"Failed to parse multihop completion for input: {generation}"
+ )
+ logging.error(f"Error: {e}")
+
+ parsed_actions = self.parse_jsonified_tool_use_generation(actions, "Action:")
+ return generation, plan, parsed_actions
+
+ def parse(self, text: str) -> Union[List[AgentAction], AgentFinish]:
+ # Parse the structured output of the final answer.
+ if "Answer: " in text:
+ prefix_map = {
+ "answer": "Answer:",
+ "grounded_answer": "Grounded answer:",
+ "relevant_docs": "Relevant Documents:",
+ "cited_docs": "Cited Documents:",
+ }
+ parsed_answer = self.parse_answer_with_prefixes(text, prefix_map)
+ return AgentFinish({"output": parsed_answer["answer"]}, text)
+ elif any([x in text for x in ["Plan: ", "Reflection: ", "Action: "]]):
+ completion, plan, actions = self.parse_actions(text)
+ return [
+ AgentAction(action["tool_name"], action["parameters"]["query"], text)
+ for action in actions
+ ]
+ else:
+ raise ValueError(
+ "\nCould not parse generation as it did not contain Plan, Reflection,"
+ + f"Action, or Answer. Input: {text}\n\n"
+ )
+
+
+def render_tool_description(tool: BaseTool) -> str:
+ """Render the tool in the style of a Python function."""
+ def get_type(type_: str, is_optional: bool) -> str:
+ if is_optional:
+ return f"Optional[{type_}]"
+ else:
+ return type_
+
+ def function_signature(tool_: BaseTool) -> str:
+ signature = []
+ for parameter_name, parameter_definition in tool_.args.items():
+ type_ = get_type(parameter_definition.get("type"), "default" in parameter_definition)
+ signature += f"{parameter_name}: {type_}"
+ return f"def {tool_.name}({",".join(signature)}) -> List[Dict]"
+
+ def args_description(tool_: BaseTool) -> str:
+ if not tool_.args:
+ return ""
+ rendered_args = []
+ for parameter_name, parameter_definition in tool_.args.items():
+ type_ = get_type(parameter_definition.get("type"), "default" in parameter_definition)
+ rendered_args += f"{parameter_name} ({type_}): {parameter_definition.get("description")}"
+ rendered_args = "\n ".join(rendered_args)
+
+ return """
+ Args:
+ """ + rendered_args
+
+ template = PromptTemplate(template_format="f-string").from_template("""```python
+ {signature}
+ \"\"\"
+ {description}{args_description}
+ \"\"\"
+ pass
+ ```""")
+ return template.format(
+ signature=function_signature(tool),
+ description=tool.description,
+ args_description=args_description,
+ )
+
+
+def format_cohere_log_to_str(
+ intermediate_steps: List[tuple[AgentAction, str]],
+ observation_prefix: str = "<|END_OF_TURN_TOKEN|>\n<|START_OF_TURN_TOKEN|>"
+ + "<|SYSTEM_TOKEN|>\n",
+ llm_prefix: str = "<|END_OF_TURN_TOKEN|><|START_OF_TURN_TOKEN|>"
+ + "<|CHATBOT_TOKEN|>",
+) -> str:
+ """Construct the scratchpad that lets the agent continue its thought process."""
+ thoughts = ""
+ last_log = ""
+ # Global result idx to be used for grounded answer citation from any prior action.
+
+ result_idx = 0
+ for step_i, (action, observation) in enumerate(intermediate_steps):
+ # For parallel tool calls, dont add the action call twice, add all the results.
+ if action.log != last_log:
+ thoughts += action.log
+ last_log = action.log
+ if step_i > 0:
+ thoughts += "\n"
+ observation_str = f"Document {result_idx}\n{observation}"
+ result_idx += 1
+ thoughts += f"{observation_prefix}{observation_str}{llm_prefix}"
+
+ return thoughts
diff --git a/libs/partners/cohere/langchain_cohere/multi_hop/prompt.py b/libs/partners/cohere/langchain_cohere/multi_hop/prompt.py
new file mode 100644
index 0000000000000..bef92fab3aacb
--- /dev/null
+++ b/libs/partners/cohere/langchain_cohere/multi_hop/prompt.py
@@ -0,0 +1,83 @@
+# flake8: noqa
+from datetime import datetime
+from langchain_core.prompts import PromptTemplate
+
+default_basic_rules = (
+ "You are a powerful language agent trained by Cohere to help people. "
+ + "You are capable of complex reasoning and augmented with a number of tools. "
+ + "Your job is to plan and reason about how you will use and consume the output of these tools to best help the user. You will see a conversation history between yourself and a user, ending with an utterance from the user. You will then see an instruction informing you what kind of response to generate. You will construct a plan and then perform a number of reasoning and action steps to solve the problem. When you have determined the answer to the user's request, you will cite your sources in your answers, according the instructions."
+)
+
+now = datetime.now().strftime("%A, %B %d, %Y %H:%M:%S")
+default_task_context = f"""You use your advanced complex reasoning capabilities to help people by answering their questions and other requests interactively. You will be asked a very wide array of requests on all kinds of topics. You will be equipped with a wide range of search engines or similar tools to help you, which you use to research your answer. You may need to use multiple tools in parallel or sequentially to complete your task. You should focus on serving the user's needs as best you can, which will be wide-ranging. The current date is {now}."""
+
+default_style_guide = """Unless the user asks for a different style of answer, you should answer in full sentences, using proper grammar and spelling."""
+
+default_safety_rules = """The instructions in this section override those in the task description and style guide sections. Don't answer questions that are harmful or immoral."""
+
+default_system_prefix = """<|START_OF_TURN_TOKEN|><|SYSTEM_TOKEN|>"""
+
+structured_preamble_template = """{SYSTEM_PREFIX}# Introduction:
+
+This document details the task you must accomplish. \
+Read it carefully and always follow its instructions.
+
+## Safety Preamble
+{SAFETY_PREAMBLE}
+
+## System Preamble
+### Basic Rules
+{BASIC_RULES}
+
+## User Preamble
+### Task and Context
+{TASK_CONTEXT}
+
+### Style Guide
+{STYLE_GUIDE}"""
+
+
+def render_structured_preamble(
+ system_prefix: str = default_system_prefix,
+ basic_rules: str = default_basic_rules,
+ task_context: str = default_task_context,
+ style_guide: str = default_style_guide,
+ safety_rules: str = default_safety_rules,
+) -> str:
+ return structured_preamble_template.format(
+ SYSTEM_PREFIX=system_prefix,
+ BASIC_RULES=basic_rules,
+ TASK_CONTEXT=task_context,
+ STYLE_GUIDE=style_guide,
+ SAFETY_PREAMBLE=safety_rules,
+ )
+
+
+rendered_structured_preamble = render_structured_preamble()
+
+multi_hop_instruction = """Carefully perform the following instructions, in order, starting each with a new line.
+Firstly, You may need to use complex and advanced reasoning to complete your task and answer the question. Think about how you can use the provided tools to answer the question and come up with a high level plan you will execute.
+Write 'Plan:' followed by an initial high level plan of how you will solve the problem including the tools and steps required.
+Secondly, Carry out your plan by repeatedly using actions, reasoning over the results, and re-evaluating your plan. Perform Action, Observation, Reflection steps with the following format. Write 'Action:' followed by a json formatted action containing the "tool_name" and "parameters"
+ Next you will analyze the 'Observation:', this is the result of the action.
+After that you should always think about what to do next. Write 'Reflection:' followed by what you've figured out so far, any changes you need to make to your plan, and what you will do next including if you know the answer to the question.
+... (this Action/Observation/Reflection can repeat N times)
+Thirdly, Decide which of the retrieved documents are relevant to the user's last input by writing 'Relevant Documents:' followed by comma-separated list of document numbers. If none are relevant, you should instead write 'None'.
+Fourthly, Decide which of the retrieved documents contain facts that should be cited in a good answer to the user's last input by writing 'Cited Documents:' followed a comma-separated list of document numbers. If you dont want to cite any of them, you should instead write 'None'.
+Fifthly, Write 'Answer:' followed by a response to the user's last input in high quality natural english. Use the retrieved documents to help you. Do not insert any citations or grounding markup.
+Finally, Write 'Grounded answer:' followed by a response to the user's last input in high quality natural english. Use the symbols and to indicate when a fact comes from a document in the search result, e.g my fact for a fact from document 4."""
+
+
+multi_hop_prompt_template = PromptTemplate.from_template(
+ """{structured_preamble}
+
+### Available Tools
+Here is a list of tools that you have available to you:
+
+{tools}<|END_OF_TURN_TOKEN|><|START_OF_TURN_TOKEN|><|USER_TOKEN|>{input}<|END_OF_TURN_TOKEN|><|START_OF_TURN_TOKEN|><|SYSTEM_TOKEN|>{multi_hop_instruction}<|END_OF_TURN_TOKEN|><|START_OF_TURN_TOKEN|><|CHATBOT_TOKEN|>
+{agent_scratchpad}
+"""
+).partial(
+ multi_hop_instruction=multi_hop_instruction,
+ structured_preamble=rendered_structured_preamble,
+)