diff --git a/.eslintrc.js b/.eslintrc.js new file mode 100644 index 00000000..d9005572 --- /dev/null +++ b/.eslintrc.js @@ -0,0 +1,57 @@ +/** + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + * + * @format + */ + +const OFF = 0; +const WARNING = 1; +const ERROR = 2; + +module.exports = { + root: true, + env: { + browser: true, + commonjs: true, + jest: true, + node: true, + }, + parser: "@babel/eslint-parser", + parserOptions: { + allowImportExportEverywhere: true, + }, + extends: ["airbnb", "prettier"], + plugins: ["react-hooks", "header"], + ignorePatterns: [ + "build", + "docs/api", + "node_modules", + "docs/_static", + "static", + ], + rules: { + // Ignore certain webpack alias because it can't be resolved + "import/no-unresolved": [ + ERROR, + { ignore: ["^@theme", "^@docusaurus", "^@generated"] }, + ], + "import/extensions": OFF, + "react/jsx-filename-extension": OFF, + "react-hooks/rules-of-hooks": ERROR, + "react/prop-types": OFF, // PropTypes aren't used much these days. + "react/function-component-definition": [ + WARNING, + { + namedComponents: "function-declaration", + unnamedComponents: "arrow-function", + }, + ], + "no-unused-vars": WARNING, + "import/prefer-default-export": WARNING, + "react/jsx-props-no-spreading": OFF, + "no-empty-pattern": WARNING, + }, +}; diff --git a/.github/workflows/format-lint.yml b/.github/workflows/format-lint.yml new file mode 100644 index 00000000..1705d740 --- /dev/null +++ b/.github/workflows/format-lint.yml @@ -0,0 +1,52 @@ +# This workflow will do a clean installation of node dependencies, cache/restore them, build the source code and run tests across different versions of node +# For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-nodejs + +name: CI (Lint/Format) + +on: + push: + branches: ["main"] + pull_request: + workflow_dispatch: # Allows triggering the workflow manually in GitHub UI + + +# If another push to the same PR or branch happens while this workflow is still running, +# cancel the earlier run in favor of the next run. +# +# There's no point in testing an outdated version of the code. GitHub only allows +# a limited number of job runners to be active at the same time, so it's better to cancel +# pointless jobs early so that more useful jobs can run sooner. +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +jobs: + lint: + name: Check linting + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - name: Use Node.js 18.x + uses: actions/setup-node@v3 + with: + node-version: 18.x + cache: "yarn" + - name: Install dependencies + run: yarn install --immutable --mode=skip-build + - name: Check linting + run: yarn run lint + + format: + name: Check formatting + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - name: Use Node.js 18.x + uses: actions/setup-node@v3 + with: + node-version: 18.x + cache: "yarn" + - name: Install dependencies + run: yarn install --immutable --mode=skip-build + - name: Check formatting + run: yarn run format:check diff --git a/docs/evaluation/faq/evaluator-implementations.mdx b/docs/evaluation/faq/evaluator-implementations.mdx index ef023b00..80d3476d 100644 --- a/docs/evaluation/faq/evaluator-implementations.mdx +++ b/docs/evaluation/faq/evaluator-implementations.mdx @@ -53,10 +53,10 @@ Three QA evaluators you can load are: `"qa"`, `"context_qa"`, `"cot_qa"`. Based - The `"qa"` evaluator ([reference](https://api.python.langchain.com/en/latest/evaluation/langchain.evaluation.qa.eval_chain.QAEvalChain.html#langchain-evaluation-qa-eval-chain-qaevalchain)) instructs an llm to directly grade a response as "correct" or "incorrect" based on the reference answer. - The `"context_qa"` evaluator ([reference](https://api.python.langchain.com/en/latest/evaluation/langchain.evaluation.qa.eval_chain.ContextQAEvalChain.html#langchain.evaluation.qa.eval_chain.ContextQAEvalChain)) instructs the LLM chain to use reference "context" (provided throught the example outputs) in determining correctness. This is useful if you have a larger corpus of grounding docs but don't have ground truth answers to a query. - The `"cot_qa"` evaluator ([reference](https://api.python.langchain.com/en/latest/evaluation/langchain.evaluation.qa.eval_chain.CotQAEvalChain.html#langchain.evaluation.qa.eval_chain.CotQAEvalChain)) is similar to the "context_qa" evaluator, except it instructs the LLMChain to use chain of thought "reasoning" before determining a final verdict. This tends to lead to responses that better correlate with human labels, for a slightly higher token and runtime cost. - {" "} - - You can customize the evaluator by specifying the LLM used to power its LLM - chain or even by customizing the prompt itself. Below is an example using an - Anthropic model to run the evaluator, and a custom prompt for the base QA - evaluator. Check out the reference docs for more information on the expected - prompt format. - +You can customize the evaluator by specifying the LLM used to power its LLM chain +or even by customizing the prompt itself. Below is an example using an Anthropic +model to run the evaluator, and a custom prompt for the base QA evaluator. Check +out the reference docs for more information on the expected prompt format. + + ]} + groupId="client-language" +/> ## Criteria Evaluators (No Labels) diff --git a/docs/tracing/faq/logging_and_viewing.mdx b/docs/tracing/faq/logging_and_viewing.mdx index adbce104..6a338b1b 100644 --- a/docs/tracing/faq/logging_and_viewing.mdx +++ b/docs/tracing/faq/logging_and_viewing.mdx @@ -52,6 +52,7 @@ Additionally, you will need to set `LANGCHAIN_TRACING_V2='true'` if you plan to - LangChain (Python or JS) - `@traceable` decorator or `wrap_openai` method in the Python SDK + ::: ( - -); +export function ClientInstallationCodeTabs() { + return ( + + ); +} diff --git a/src/components/Hub.js b/src/components/Hub.js index 01018c14..be330e4f 100644 --- a/src/components/Hub.js +++ b/src/components/Hub.js @@ -10,39 +10,41 @@ import { ShellBlock, } from "./InstructionsWithCode"; -export const HubInstallationCodeTabs = () => ( - -); +export function HubInstallationCodeTabs() { + return ( + + ); +} -export const HubPullCodeTabs = ({}) => { +export function HubPullCodeTabs() { const pyBlock = `from langchain import hub # pull a chat prompt @@ -94,9 +96,9 @@ console.log(result);`; ); -}; +} -export const HubPushCodeTabs = ({}) => { +export function HubPushCodeTabs() { const pyBlock = `from langchain import hub from langchain.prompts.chat import ChatPromptTemplate @@ -131,4 +133,4 @@ await hub.push("/my-first-prompt", prompt);`; ); -}; +} diff --git a/src/components/InstructionsWithCode.js b/src/components/InstructionsWithCode.js index 18eb769a..7a017f29 100644 --- a/src/components/InstructionsWithCode.js +++ b/src/components/InstructionsWithCode.js @@ -7,7 +7,7 @@ export function LangChainPyBlock(content) { return { value: "langchain-py", label: "LangChain (Python)", - content: content, + content, language: "python", }; } @@ -16,7 +16,7 @@ export function LangChainJSBlock(content) { return { value: "langchain-js", label: "LangChain (JS)", - content: content, + content, language: "typescript", }; } @@ -25,7 +25,7 @@ export function TypeScriptBlock(content) { return { value: "typescript", label: "TypeScript SDK", - content: content, + content, language: "typescript", }; } @@ -34,7 +34,7 @@ export function PythonBlock(content) { return { value: "python", label: "Python SDK", - content: content, + content, language: "python", }; } @@ -43,27 +43,35 @@ export function APIBlock(content) { return { value: "api", label: "API (Using Python Requests)", - content: content, + content, language: "python", }; } export function ShellBlock(content, value = "shell", label = "Shell") { return { - value: value, - label: label, - content: content, + value, + label, + content, }; } -export const CodeTabs = ({ tabs, groupId }) => ( - - {tabs.map((tab, index) => ( - - - {tab.content} - - - ))} - -); +export function CodeTabs({ tabs, groupId }) { + return ( + + {tabs.map((tab, index) => { + const key = `${groupId}-${index}`; + return ( + + + {tab.content} + + + ); + })} + + ); +} diff --git a/src/components/QuickStart.js b/src/components/QuickStart.js index e4163740..b10d08ed 100644 --- a/src/components/QuickStart.js +++ b/src/components/QuickStart.js @@ -1,3 +1,7 @@ +import CodeBlock from "@theme/CodeBlock"; +import React from "react"; +import TabItem from "@theme/TabItem"; +import Tabs from "@theme/Tabs"; import { CodeTabs, PythonBlock, @@ -5,11 +9,6 @@ import { TypeScriptBlock, } from "./InstructionsWithCode"; -import CodeBlock from "@theme/CodeBlock"; -import React from "react"; -import TabItem from "@theme/TabItem"; -import Tabs from "@theme/Tabs"; - export const TypeScriptSDKTracingCode = () => `import { OpenAI } from "openai"; import { traceable } from "langsmith/traceable"; @@ -28,13 +27,16 @@ const pipeline = traceable(async (user_input) => { await pipeline("Hello, world!") // Out: Hello there! How can I assist you today?`; -export const TypeScriptSDKTracingCodeBlock = () => ( - {TypeScriptSDKTracingCode()} -); +export function TypeScriptSDKTracingCodeBlock() { + return ( + {TypeScriptSDKTracingCode()} + ); +} -export const PythonAPITracingCodeBlock = () => ( - - {`import openai +export function PythonAPITracingCodeBlock() { + return ( + + {`import openai import requests from datetime import datetime from uuid import uuid4 @@ -95,8 +97,9 @@ chat_completion = client.chat.completions.create(model="gpt-3.5-turbo", messages # End runs patch_run(child_run_id, chat_completion.dict()) patch_run(parent_run_id, {"answer": chat_completion.choices[0].message.content})`} - -); + + ); +} export const PythonSDKTracingCode = () => `import openai @@ -114,69 +117,75 @@ def pipeline(user_input: str): pipeline("Hello, world!") # Out: Hello there! How can I assist you today?`; -export const PythonSDKTracingCodeBlock = () => ( - {PythonSDKTracingCode()} -); - -export const LangChainInstallationCodeTabs = () => ( - -); - -export const ConfigureSDKEnvironmentCodeTabs = ({}) => ( - {PythonSDKTracingCode()}; +} + +export function LangChainInstallationCodeTabs() { + return ( + + ); +} + +export function ConfigureSDKEnvironmentCodeTabs({}) { + return ( + # The below examples use the OpenAI API, though it's not necessary in general export OPENAI_API_KEY=`), - ]} - groupId="client-language" - /> -); - -export const ConfigureEnvironmentCodeTabs = ({}) => ( - + ); +} + +export function ConfigureEnvironmentCodeTabs({}) { + return ( + # The below examples use the OpenAI API, though it's not necessary in general export OPENAI_API_KEY=`), - ]} - groupId="client-language" - /> -); + ]} + groupId="client-language" + /> + ); +} -export const LangChainQuickStartCodeTabs = ({}) => { +export function LangChainQuickStartCodeTabs({}) { const simpleTSBlock = `import { ChatOpenAI } from "@langchain/openai"; import { ChatPromptTemplate } from "@langchain/core/prompts"; import { StringOutputParser } from "@langchain/core/output_parsers"; @@ -242,7 +251,7 @@ chain.invoke({"question": question, "context": context})`} ); -}; +} const TraceableQuickStart = PythonBlock(`from typing import Any, Iterable\n import openai @@ -272,21 +281,24 @@ for tok in my_chat_bot("Summarize this morning's meetings."): print(tok, end="") # See an example run at: https://smith.langchain.com/public/3e853ad8-77ce-404d-ad4c-05726851ad0f/r`); -export const TraceableQuickStartCodeBlock = ({}) => ( - - {TraceableQuickStart.content} - -); - -export const TraceableThreadingCodeBlock = ({}) => ( - - {`import asyncio +export function TraceableQuickStartCodeBlock({}) { + return ( + + {TraceableQuickStart.content} + + ); +} + +export function TraceableThreadingCodeBlock({}) { + return ( + + {`import asyncio import datetime from concurrent.futures import ThreadPoolExecutor from typing import Any, Dict, List\n @@ -350,18 +362,20 @@ async def nested_chain(text: str, run_tree: RunTree, **kwargs: Any) -> str: ) return "\\n".join([future.result() for future in futures])\n\n asyncio.run(nested_chain("Summarize meeting"))`} - -); - -export const RunTreeQuickStartCodeTabs = ({}) => ( - + ); +} + +export function RunTreeQuickStartCodeTabs({}) { + return ( + -); + ]} + groupId="client-language" + /> + ); +} diff --git a/src/components/RunTree.js b/src/components/RunTree.js index af782c68..893e057d 100644 --- a/src/components/RunTree.js +++ b/src/components/RunTree.js @@ -1,10 +1,11 @@ import React from "react"; import { CodeTabs, PythonBlock, TypeScriptBlock } from "./InstructionsWithCode"; -export const RunTreeExampleCodeTabs = () => ( - -); + ]} + groupId="client-language" + /> + ); +} diff --git a/src/components/TracingFaq.js b/src/components/TracingFaq.js index 20a2f2f3..63c81354 100644 --- a/src/components/TracingFaq.js +++ b/src/components/TracingFaq.js @@ -3,7 +3,7 @@ import React from "react"; import TabItem from "@theme/TabItem"; import Tabs from "@theme/Tabs"; -export const AccessRunIdBlock = ({}) => { +export function AccessRunIdBlock({}) { const callbackPythonBlock = `from langchain import chat_models, prompts, callbacks chain = ( prompts.ChatPromptTemplate.from_template("Say hi to {name}") @@ -110,4 +110,4 @@ console.log(response.__run);`; ); -}; +} diff --git a/src/hooks/useColorScheme.js b/src/hooks/useColorScheme.js index a75af787..fb958ebf 100644 --- a/src/hooks/useColorScheme.js +++ b/src/hooks/useColorScheme.js @@ -9,6 +9,6 @@ export function useColorScheme() { mode: systemMode, isDarkMode, isLightMode: !isDarkMode, - setMode: setMode, + setMode, }; } diff --git a/src/theme/ColorModeToggle/index.js b/src/theme/ColorModeToggle/index.js index 06eb6194..42c4ad37 100644 --- a/src/theme/ColorModeToggle/index.js +++ b/src/theme/ColorModeToggle/index.js @@ -14,9 +14,5 @@ export default function ColorModeToggleWrapper(props) { setMode(value); }, [value]); - return ( - <> - - - ); + return ; } diff --git a/src/theme/SearchBar.js b/src/theme/SearchBar.js index 44aeba03..42d4a946 100644 --- a/src/theme/SearchBar.js +++ b/src/theme/SearchBar.js @@ -2,9 +2,5 @@ import React from "react"; import SearchBar from "@theme-original/SearchBar"; export default function SearchBarWrapper(props) { - return ( - <> - - - ); + return ; }