Skip to content

Commit

Permalink
Merge pull request #1 from Tanuki/support/togetherai
Browse files Browse the repository at this point in the history
[WIP] Support/togetherai
  • Loading branch information
JackHopkins authored Feb 3, 2024
2 parents f47b23f + 0e5628c commit 59a59bd
Show file tree
Hide file tree
Showing 85 changed files with 4,285 additions and 24,188 deletions.
4 changes: 0 additions & 4 deletions .env

This file was deleted.

33 changes: 33 additions & 0 deletions .eslintrc.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
root: true
parser: "@typescript-eslint/parser"
plugins:
- "@typescript-eslint"
- "node"
- "prettier"
parserOptions:
project:
- "./tsconfig.json"
extends:
- "eslint:recommended"
- "plugin:node/recommended"
- "plugin:@typescript-eslint/eslint-recommended"
- "plugin:@typescript-eslint/recommended"
- "plugin:@typescript-eslint/recommended-requiring-type-checking"
- "plugin:prettier/recommended"
rules:
prettier/prettier: "warn"
node/no-missing-import: "off"
node/no-empty-function: "off"
node/no-unsupported-features/es-syntax: "off"
node/no-missing-require: "off"
node/shebang: "off"
"@typescript-eslint/no-use-before-define": "off"
quotes:
- "warn"
- "single"
- avoidEscape: true
node/no-unpublished-import: "off"
"@typescript-eslint/no-unsafe-assignment": "off"
"@typescript-eslint/no-var-requires": "off"
"@typescript-eslint/ban-ts-comment": "off"
"@typescript-eslint/no-explicit-any": "off"
26 changes: 22 additions & 4 deletions .github/workflows/pr.yml
Original file line number Diff line number Diff line change
@@ -1,9 +1,27 @@
# Reusable workflow for PRs; to eject, you can replace this file with
# https://github.com/ryansonshine/ryansonshine/blob/main/.github/workflows/pr.yml
name: Pull Request

on: [pull_request]
on:
workflow_call:

jobs:
build:
uses: ryansonshine/ryansonshine/.github/workflows/pr.yml@main
runs-on: ubuntu-latest

strategy:
matrix:
node-version: [16.x, 18.x]

steps:
- uses: actions/checkout@v3
- name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v3
with:
node-version: ${{ matrix.node-version }}
- run: npm ci
- run: npm run build --if-present
- run: npm test --coverage
- name: Upload Code Coverage
uses: codecov/[email protected]
with:
token: ${{ secrets.CODECOV_TOKEN }} # Not needed for public repos
directory: ./coverage
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -117,3 +117,6 @@ dist

# Compiled code
lib/
/.env
.env
tests/testModelProviders/.env
4 changes: 3 additions & 1 deletion .eslintrc.js → .old.eslintrc.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,9 @@ export default {
plugins: ['@typescript-eslint', 'node', 'prettier'],
parserOptions: {
tsconfigRootDir: __dirname,
project: ['./tsconfig.json'],
project: './tsconfig.json',
ecmaVersion: 2020,
sourceType: 'module'
},
extends: [
'eslint:recommended',
Expand Down
70 changes: 44 additions & 26 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
# Tanuki <span style="font-family:Papyrus; font-size:2em;">🦝</span> ![Discord](https://img.shields.io/discord/1168948553222197248)
Easily build LLM-powered apps that get cheaper and faster over time.
# Tanuki <span style="font-family:Papyrus; font-size:2em;">🦝</span> ![Discord](https://img.shields.io/discord/1168948553222197248) [![codecov](https://codecov.io/gh/Tanuki/tanuki.ts/branch/main/graph/badge.svg?token=b169ecba-fa1c-43ee-a9e0-18597d2aaffa)](https://codecov.io/gh/Tanuki/tanuki.ts)

Build LLM-powered apps that get cheaper and faster over time.

---

Expand Down Expand Up @@ -40,17 +41,19 @@ Lastly, the more you use Tanuki functions, the cheaper and faster they gets (up
* Declare the function that you want Tanuki to provide.
*/
class Functions {
someFunction = patch<TypedOutput, TypedInput>()`Include the instruction that your function will execute`;
static someFunction = patch<TypedOutput, TypedInput>()
`{The instruction that your function will execute}`;
}

/**
* Align your function to the expected behaviour using Jest-like assertions
*/
Tanuki.align(async (it) => {
it("testSomeFunction", async (expect) => {
it("should correctly classify positive affirmation", async (expect) => {
const exampleTypedInput: TypedInput = "I love you";
const exampleTypedOutput: TypedOutput = "Good";
expect(await new Functions().someFunction(exampleTypedInput)).toEqual(exampleTypedOutput);
const result = await Functions.someFunction(exampleTypedInput);
expect(result).toEqual(exampleTypedOutput);
});
});
```
Expand All @@ -68,6 +71,7 @@ Tanuki.align(async (it) => {
<!-- TOC --><a name="installation-and-getting-started"></a>
## Installation and Getting Started
<!-- TOC --><a name="installation"></a>

### Installation
```bash
npm install tanuki.ts
Expand All @@ -84,7 +88,8 @@ export AWS_SECRET_ACCESS_KEY=...
export AWS_ACCESS_KEY_ID=...
```

Next, we need to install the Tanuki type transformer. This will allow Tanuki to be aware of your patched functions and types at runtime, as these types are usually erased by the Typescript compiler when transpiling into Javascript.
#### Default Setup
Next, we need to install the Tanuki type transformer. This will allow Tanuki to be aware of your patched functions and types at runtime, as these types are erased when transpiling into Javascript.
```typescript
npm install ts-patch --save-dev
npx ts-patch install
Expand All @@ -103,15 +108,28 @@ Next, you need to add the Tanuki transformer to your `tsconfig.json` file:
}
}
```
This is required for Tanuki to be aware of your patched functions and types at runtime, as these types are usually erased by the Typescript compiler when transpiling into Javascript.

#### Next.js Setup
As Next.js has it's own build system, you must explicitly add the Tanuki transformer to your `package.json` file instead by adding the following scripts.

```json
{
"scripts": {
"predev": "tanuki-type-compiler",
"prebuild": "tanuki-type-compiler",
"prestart": "tanuki-type-compiler"
}
}
```

This will ensure that Tanuki can extract your patched functions before the Next.js build process.


<!-- TOC --><a name="getting-started"></a>
### Getting Started

To get started:
1. Create a `patch` function stub, including your input and output types, and an instruction.
1. Create a `patch` function stub as a static member of a class, including your input and output types, and an instruction.
2. (Optional) Create jest-like equivalent assertions in a `Tanuki.align` block, declaring the expected behaviour of your patched function with different inputs.

Once you have built your code (to make Tanuki aware of your types), the `patch` function will be registered and can be invoked as normal.
Expand All @@ -133,26 +151,25 @@ type Message = string;
* Declare the function that you want Tanuki to provide.
*/
class Functions {
classifySentiment = patch<Sentiment, Message>()`Classifies message from the user based on sentiment`;
static classifySentiment = patch<Sentiment, Message>()
`Classifies message from the user based on sentiment`;
}

/**
* Align your function to the expected behavior using Jest-like assertions.
*/
Tanuki.align(async (it) => {
it("alignClassifySentiment", async (expect) => {
const functions = new Functions();
expect(await functions.classifySentiment("I love you")).toEqual('Good');
expect(await functions.classifySentiment("I hate you")).toEqual('Bad');
expect(await functions.classifySentiment("People from Phoenix are called Phoenicians")).toBeNull();
expect(await Functions.classifySentiment("I love you")).toEqual('Good');
expect(await Functions.classifySentiment("I hate you")).toEqual('Bad');
expect(await Functions.classifySentiment("People from Phoenix are called Phoenicians")).toBeNull();
});
});

// Example usage of the patched function somewhere else in your code
const runExamples = async () => {
const functions = new Functions();
console.log(await functions.classifySentiment("I like you")); // Expect 'Good' or null
console.log(await functions.classifySentiment("Apples might be red")); // Expect null
console.log(await Functions.classifySentiment("I like you")); // Expect 'Good' or null
console.log(await Functions.classifySentiment("Apples might be red")); // Expect null
};

runExamples();
Expand Down Expand Up @@ -264,15 +281,16 @@ Test-Driven Alignment (TDA) adapts this concept to align the behavior of a patch

To align the behaviour of your patched function to your needs, decorate a function with `@align` and assert the outputs of the function with the ‘assert’ statement as is done with standard tests.

```python
@tanuki.align
def align_classify_sentiment():
assert classify_sentiment("I love this!") == 'Good'
assert classify_sentiment("I hate this.") == 'Bad'

@tanuki.align
def align_score_sentiment():
assert score_sentiment("I like you") == 7
```typescript
import { Finance } from './finance';
import { Tanuki } from 'tanuki.ts';

Tanuki.align((it) => {
it("should extract company names whose stock is increasing", async (expect) => {
const input1 = "Consumer spending makes up a huge fraction of the overall economy. Investors are therefore always looking at consumers to try to gauge whether their financial condition remains healthy. That's a big part of why the stock market saw a bear market in 2022, as some feared that a consumer-led recession would result in much weaker business performance across the sector.\nHowever, that much-anticipated recession hasn't happened yet, and there's still plenty of uncertainty about the future direction of consumer-facing stocks. A pair of earnings reports early Wednesday didn't do much to resolve the debate, as household products giant Procter & Gamble (PG 0.13%) saw its stock rise even as recreational vehicle manufacturer Winnebago Industries (WGO 0.58%) declined.";
expect(await Finance.extractStockWinnersVol6(input1)).toEqual(["Procter & Gamble"]);
})
})
```

By writing a test that encapsulates the expected behaviour of the tanuki-patched function, you declare the contract that the function must fulfill. This enables you to:
Expand Down Expand Up @@ -307,7 +325,7 @@ We tested out model distillation using Tanuki using OpenAI models on Squad2, Spi
### Intro
<!-- TOC --><a name="what-is-tanuki-in-plain-words"></a>
#### What is Tanuki in plain words?
Tanuki is a simple and seamless way to create LLM augmented functions in python, which ensure the outputs of the LLMs follow a specific structure. Moreover, the more you call a patched function, the cheaper and faster the execution gets.
Tanuki is a simple and seamless way to create LLM augmented functions in Typescript and Python, which ensure the outputs of the LLMs follow a specific structure. Moreover, the more you call a patched function, the cheaper and faster the execution gets.

<!-- TOC --><a name="how-does-this-compare-to-other-frameworks-like-langchain"></a>
#### How does this compare to other frameworks like LangChain?
Expand Down
9 changes: 5 additions & 4 deletions jest.config.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,13 @@ export default {
testEnvironment: 'node',
testMatch: ['**/tests/**/*.spec.ts', '**/tests/**/*.test.ts', '**/tests/*.spec.ts', '**/tests/*.test.ts'],
transform: {
'^.+\\.tsx?$': 'babel-jest'
'^.+\\.tsx?$': 'ts-jest'
},
extensionsToTreatAsEsm: ['.ts'],
collectCoverageFrom: [
'<rootDir>/src/**/*.ts',
'!<rootDir>/src/types/**/*.ts',
'!<rootDir>/src/models/**/*.ts',
],
globals: {
'ts-jest': {
Expand All @@ -17,7 +18,7 @@ export default {
useESM: true,
},
},
moduleNameMapper: {
'^(\\.{1,2}/.*)\\.js$': '$1',
},
//moduleNameMapper: {
// '^(\\.{1,2}/.*)\\.js$': '$1',
//},
};
Loading

0 comments on commit 59a59bd

Please sign in to comment.