mirror of
https://github.com/hwchase17/langchain.git
synced 2025-06-24 15:43:54 +00:00
Add basic critique revise template (#12688)
@baskaryan @hwchase17 --------- Co-authored-by: Erick Friis <erick@langchain.dev>
This commit is contained in:
parent
ee3ceb0fb8
commit
cf271784fa
21
templates/basic-critique-revise/LICENSE
Normal file
21
templates/basic-critique-revise/LICENSE
Normal file
@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2023 LangChain, Inc.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
66
templates/basic-critique-revise/README.md
Normal file
66
templates/basic-critique-revise/README.md
Normal file
@ -0,0 +1,66 @@
|
||||
# basic-critique-revise
|
||||
|
||||
TODO: What does this package do
|
||||
|
||||
## Environment Setup
|
||||
|
||||
TODO: What environment variables need to be set (if any)
|
||||
|
||||
## Usage
|
||||
|
||||
To use this package, you should first have the LangChain CLI installed:
|
||||
|
||||
```shell
|
||||
pip install -U "langchain-cli[serve]"
|
||||
```
|
||||
|
||||
To create a new LangChain project and install this as the only package, you can do:
|
||||
|
||||
```shell
|
||||
langchain app new my-app --package basic-critique-revise
|
||||
```
|
||||
|
||||
If you want to add this to an existing project, you can just run:
|
||||
|
||||
```shell
|
||||
langchain app add basic-critique-revise
|
||||
```
|
||||
|
||||
And add the following code to your `server.py` file:
|
||||
```python
|
||||
from basic_critique_revise import chain as basic_critique_revise_chain
|
||||
|
||||
add_routes(app, basic_critique_revise_chain, path="/basic-critique-revise")
|
||||
```
|
||||
|
||||
(Optional) Let's now configure LangSmith.
|
||||
LangSmith will help us trace, monitor and debug LangChain applications.
|
||||
LangSmith is currently in private beta, you can sign up [here](https://smith.langchain.com/).
|
||||
If you don't have access, you can skip this section
|
||||
|
||||
|
||||
```shell
|
||||
export LANGCHAIN_TRACING_V2=true
|
||||
export LANGCHAIN_API_KEY=<your-api-key>
|
||||
export LANGCHAIN_PROJECT=<your-project> # if not specified, defaults to "default"
|
||||
```
|
||||
|
||||
If you are inside this directory, then you can spin up a LangServe instance directly by:
|
||||
|
||||
```shell
|
||||
langchain serve
|
||||
```
|
||||
|
||||
This will start the FastAPI app with a server is running locally at
|
||||
[http://localhost:8000](http://localhost:8000)
|
||||
|
||||
We can see all templates at [http://127.0.0.1:8000/docs](http://127.0.0.1:8000/docs)
|
||||
We can access the playground at [http://127.0.0.1:8000/basic-critique-revise/playground](http://127.0.0.1:8000/basic-critique-revise/playground)
|
||||
|
||||
We can access the template from code with:
|
||||
|
||||
```python
|
||||
from langserve.client import RemoteRunnable
|
||||
|
||||
runnable = RemoteRunnable("http://localhost:8000/basic-critique-revise")
|
||||
```
|
@ -0,0 +1,3 @@
|
||||
from basic_critique_revise.chain import chain
|
||||
|
||||
__all__ = ["chain"]
|
143
templates/basic-critique-revise/basic_critique_revise/chain.py
Normal file
143
templates/basic-critique-revise/basic_critique_revise/chain.py
Normal file
@ -0,0 +1,143 @@
|
||||
import json
|
||||
from datetime import datetime
|
||||
from enum import Enum
|
||||
from operator import itemgetter
|
||||
from typing import Any, Dict, Sequence
|
||||
|
||||
from langchain.chains.openai_functions import convert_to_openai_function
|
||||
from langchain.chat_models import ChatOpenAI
|
||||
from langchain.prompts import ChatPromptTemplate
|
||||
from langchain.pydantic_v1 import BaseModel, Field, ValidationError, conint
|
||||
from langchain.schema.runnable import (
|
||||
Runnable,
|
||||
RunnableBranch,
|
||||
RunnableLambda,
|
||||
RunnablePassthrough,
|
||||
)
|
||||
|
||||
|
||||
class TaskType(str, Enum):
|
||||
call = "Call"
|
||||
message = "Message"
|
||||
todo = "Todo"
|
||||
in_person_meeting = "In-Person Meeting"
|
||||
email = "Email"
|
||||
mail = "Mail"
|
||||
text = "Text"
|
||||
open_house = "Open House"
|
||||
|
||||
|
||||
class Task(BaseModel):
|
||||
title: str = Field(..., description="The title of the tasks, reminders and alerts")
|
||||
due_date: datetime = Field(
|
||||
..., description="Due date. Must be a valid ISO date string with timezone"
|
||||
)
|
||||
task_type: TaskType = Field(None, description="The type of task")
|
||||
|
||||
|
||||
class Tasks(BaseModel):
|
||||
"""JSON definition for creating tasks, reminders and alerts"""
|
||||
|
||||
tasks: Sequence[Task]
|
||||
|
||||
|
||||
template = """Respond to the following user query to the best of your ability:
|
||||
|
||||
{query}"""
|
||||
|
||||
generate_prompt = ChatPromptTemplate.from_template(template)
|
||||
|
||||
function_args = {"functions": [convert_to_openai_function(Tasks)]}
|
||||
|
||||
task_function_call_model = ChatOpenAI(model="gpt-3.5-turbo").bind(**function_args)
|
||||
|
||||
output_parser = RunnableLambda(
|
||||
lambda x: json.loads(
|
||||
x.additional_kwargs.get("function_call", {}).get("arguments", '""')
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
revise_template = """
|
||||
Based on the provided context, fix the incorrect result of the original prompt
|
||||
and the provided errors. Only respond with an answer that satisfies the
|
||||
constraints laid out in the original prompt and fixes the Pydantic errors.
|
||||
|
||||
Hint: Datetime fields must be valid ISO date strings.
|
||||
|
||||
<context>
|
||||
<original_prompt>
|
||||
{original_prompt}
|
||||
</original_prompt>
|
||||
<incorrect_result>
|
||||
{completion}
|
||||
</incorrect_result>
|
||||
<errors>
|
||||
{error}
|
||||
</errors>
|
||||
</context>"""
|
||||
|
||||
revise_prompt = ChatPromptTemplate.from_template(revise_template)
|
||||
|
||||
revise_chain = revise_prompt | task_function_call_model | output_parser
|
||||
|
||||
|
||||
def output_validator(output):
|
||||
try:
|
||||
Tasks.validate(output["completion"])
|
||||
except ValidationError as e:
|
||||
return str(e)
|
||||
|
||||
return None
|
||||
|
||||
|
||||
class IntermediateType(BaseModel):
|
||||
error: str
|
||||
completion: Dict
|
||||
original_prompt: str
|
||||
max_revisions: int
|
||||
|
||||
|
||||
validation_step = RunnablePassthrough().assign(error=RunnableLambda(output_validator))
|
||||
|
||||
|
||||
def revise_loop(input: IntermediateType) -> IntermediateType:
|
||||
revise_step = RunnablePassthrough().assign(completion=revise_chain)
|
||||
|
||||
else_step: Runnable[IntermediateType, IntermediateType] = RunnableBranch(
|
||||
(lambda x: x["error"] is None, RunnablePassthrough()),
|
||||
revise_step | validation_step,
|
||||
).with_types(input_type=IntermediateType)
|
||||
|
||||
for _ in range(max(0, input["max_revisions"] - 1)):
|
||||
else_step = RunnableBranch(
|
||||
(lambda x: x["error"] is None, RunnablePassthrough()),
|
||||
revise_step | validation_step | else_step,
|
||||
)
|
||||
return else_step
|
||||
|
||||
|
||||
revise_lambda = RunnableLambda(revise_loop)
|
||||
|
||||
|
||||
class InputType(BaseModel):
|
||||
query: str
|
||||
max_revisions: conint(ge=1, le=10) = 5
|
||||
|
||||
|
||||
chain: Runnable[Any, Any] = (
|
||||
{
|
||||
"original_prompt": generate_prompt,
|
||||
"max_revisions": itemgetter("max_revisions"),
|
||||
}
|
||||
| RunnablePassthrough().assign(
|
||||
completion=(
|
||||
RunnableLambda(itemgetter("original_prompt"))
|
||||
| task_function_call_model
|
||||
| output_parser
|
||||
)
|
||||
)
|
||||
| validation_step
|
||||
| revise_lambda
|
||||
| RunnableLambda(itemgetter("completion"))
|
||||
).with_types(input_type=InputType)
|
1473
templates/basic-critique-revise/poetry.lock
generated
Normal file
1473
templates/basic-critique-revise/poetry.lock
generated
Normal file
File diff suppressed because it is too large
Load Diff
24
templates/basic-critique-revise/pyproject.toml
Normal file
24
templates/basic-critique-revise/pyproject.toml
Normal file
@ -0,0 +1,24 @@
|
||||
[tool.poetry]
|
||||
name = "basic_critique_revise"
|
||||
version = "0.0.1"
|
||||
description = ""
|
||||
authors = []
|
||||
readme = "README.md"
|
||||
|
||||
[tool.poetry.dependencies]
|
||||
python = ">=3.8.1,<4.0"
|
||||
langchain = ">=0.0.313, <0.1"
|
||||
openai = "^0.28.1"
|
||||
|
||||
[tool.poetry.group.dev.dependencies]
|
||||
langchain-cli = ">=0.0.15"
|
||||
fastapi = "^0.104.0"
|
||||
sse-starlette = "^1.6.5"
|
||||
|
||||
[tool.langserve]
|
||||
export_module = "basic_critique_revise"
|
||||
export_attr = "chain"
|
||||
|
||||
[build-system]
|
||||
requires = ["poetry-core"]
|
||||
build-backend = "poetry.core.masonry.api"
|
0
templates/basic-critique-revise/tests/__init__.py
Normal file
0
templates/basic-critique-revise/tests/__init__.py
Normal file
Loading…
Reference in New Issue
Block a user