-
Notifications
You must be signed in to change notification settings - Fork 9
/ai/spell/search (toolshed)
#277
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from 25 commits
Commits
Show all changes
26 commits
Select commit
Hold shift + click to select a range
c914a4f
Stub search functionality
bfollington 422a87e
Stubbed search implementation
bfollington 28d84b7
Implement three basic strategy ideas for search
bfollington 2e99be5
Extract strategies and refactor logging
bfollington 58bdd25
Extract LLM library functions
bfollington 2261961
Factor out all redis code into lib
bfollington e5ed296
Format pass
bfollington 505a93e
Introduce Logger interface
bfollington 2c4174c
Improve docstrings
bfollington e8d5f21
Add types for redis
bfollington dc2d0a3
One more format pass
bfollington 379f660
Default cors() settings clipper can reach blobby
bfollington f747da6
Fix lint errors
bfollington f3f7e19
Reverse refactor, use hono/client
bfollington 21ad249
Restore state of world
bfollington cb5a676
Fix exported router types
bfollington 360cffd
Get all effects working again with hono/client
bfollington dfa9fb8
Format pass
bfollington 3684ab6
Fix lint
bfollington 9a5d50a
adding a shared llm client wrapper that can be imported and used (#280)
jakedahn 7d49f3f
Fix llm call
bfollington 2c33e8a
Fixing errors so I can run the tests
bfollington 3aa3aa5
Basic smoke tests for spell endpoints
bfollington b0b3095
Feels like this shouldn't work but it does
bfollington ef13ca1
Comment out tests
bfollington 42e06ad
Add explaination
bfollington File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,39 @@ | ||
| import { State } from "mistreevous"; | ||
| import { Logger, PrefixedLogger } from "./prefixed-logger.ts"; | ||
|
|
||
| // Handles logging and instrumentation | ||
| export abstract class BaseAgent { | ||
| protected logger: PrefixedLogger; | ||
| protected agentName: string; | ||
| protected stepDurations: Record<string, number> = {}; | ||
| protected logs: string[] = []; | ||
| protected startTime: number = 0; | ||
|
|
||
| constructor(logger: Logger, agentName: string) { | ||
| this.agentName = agentName; | ||
| this.logger = new PrefixedLogger(logger, agentName); | ||
| this.startTime = Date.now(); | ||
| } | ||
|
|
||
| protected async measureStep( | ||
| stepName: string, | ||
| fn: () => Promise<State>, | ||
| ): Promise<State> { | ||
| const start = Date.now(); | ||
| const result = await fn(); | ||
| this.stepDurations[stepName] = Date.now() - start; | ||
| this.logger.info( | ||
| `${this.agentName}: ${stepName} took ${this.stepDurations[stepName]}ms`, | ||
| ); | ||
| return result; | ||
| } | ||
|
|
||
| protected getMetadata() { | ||
| const totalDuration = Date.now() - this.startTime; | ||
| return { | ||
| totalDuration, | ||
| stepDurations: this.stepDurations, | ||
| logs: this.logs, | ||
| }; | ||
| } | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,46 @@ | ||
| import { AppType } from "@/app.ts"; | ||
| import { hc } from "hono/client"; | ||
|
|
||
| // NOTE(jake): Ideally this would be exposed via the hono client, but I wasn't | ||
| // able to get it all wired up. Importing the route definition is fine for now. | ||
| import type { GetModelsRouteQueryParams } from "@/routes/ai/llm/llm.routes.ts"; | ||
|
|
||
| const client = hc<AppType>("http://localhost:8000/"); | ||
|
|
||
| export async function listAvailableModels({ | ||
| capability, | ||
| task, | ||
| search, | ||
| }: GetModelsRouteQueryParams) { | ||
| const res = await client.api.ai.llm.models.$get({ | ||
| query: { | ||
| search, | ||
| capability, | ||
| task, | ||
| }, | ||
| }); | ||
| return res.json(); | ||
| } | ||
|
|
||
| export async function generateText( | ||
| query: Parameters<typeof client.api.ai.llm.$post>[0]["json"], | ||
| ): Promise<string> { | ||
| const res = await client.api.ai.llm.$post({ json: query }); | ||
| const data = await res.json(); | ||
|
|
||
| if ("error" in data) { | ||
| throw new Error(data.error); | ||
| } | ||
|
|
||
| if ("type" in data && data.type === "json") { | ||
| return data.body.content; | ||
| } | ||
|
|
||
| if ("content" in data) { | ||
| // bf: this is actually the case that runs, even if the types disagree | ||
| // no idea why | ||
| return (data as any).content; | ||
| } | ||
|
|
||
| throw new Error("Unexpected response from LLM server"); | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,57 @@ | ||
| export interface Logger { | ||
| // deno-lint-ignore no-explicit-any | ||
| info(...args: any[]): void; | ||
| // deno-lint-ignore no-explicit-any | ||
| error(...args: any[]): void; | ||
| // deno-lint-ignore no-explicit-any | ||
| warn(...args: any[]): void; | ||
| // deno-lint-ignore no-explicit-any | ||
| debug(...args: any[]): void; | ||
| } | ||
|
|
||
| export class PrefixedLogger implements Logger { | ||
bfollington marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| private logger: Logger; | ||
| private prefix: string; | ||
| private logMessages: string[] = []; | ||
|
|
||
| constructor(logger: Logger = console, prefix: string) { | ||
| this.logger = logger; | ||
| this.prefix = prefix; | ||
| this.info = this.info.bind(this); | ||
| this.error = this.error.bind(this); | ||
| this.warn = this.warn.bind(this); | ||
| this.debug = this.debug.bind(this); | ||
| } | ||
|
|
||
| // deno-lint-ignore no-explicit-any | ||
| info(...args: any[]) { | ||
| const message = [`[${this.prefix}]`, ...args].join(" "); | ||
| this.logMessages.push(message); | ||
| this.logger.info(message); | ||
| } | ||
|
|
||
| // deno-lint-ignore no-explicit-any | ||
| error(...args: any[]) { | ||
| const message = [`[${this.prefix}]`, ...args].join(" "); | ||
| this.logMessages.push(message); | ||
| this.logger.error(message); | ||
| } | ||
|
|
||
| // deno-lint-ignore no-explicit-any | ||
| warn(...args: any[]) { | ||
| const message = [`[${this.prefix}]`, ...args].join(" "); | ||
| this.logMessages.push(message); | ||
| this.logger.warn(message); | ||
| } | ||
|
|
||
| // deno-lint-ignore no-explicit-any | ||
| debug(...args: any[]) { | ||
| const message = [`[${this.prefix}]`, ...args].join(" "); | ||
| this.logMessages.push(message); | ||
| this.logger.debug(message); | ||
| } | ||
|
|
||
| getLogs(): string[] { | ||
| return this.logMessages; | ||
| } | ||
| } | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,17 @@ | ||
| export async function handleResponse<T>(response: Response): Promise<T> { | ||
| const data = await response.json(); | ||
|
|
||
| if ("error" in data) { | ||
| throw new Error(data.error); | ||
| } | ||
|
|
||
| if (data.type === "json") { | ||
| return data.body; | ||
| } | ||
|
|
||
| if (data instanceof Response) { | ||
| throw new Error(data.statusText); | ||
| } | ||
|
|
||
| return null as never; | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,46 @@ | ||
| import { Schema, Validator } from "jsonschema"; | ||
|
|
||
| export function checkSchemaMatch( | ||
| data: Record<string, unknown>, | ||
| schema: Schema, | ||
| ): boolean { | ||
| const validator = new Validator(); | ||
|
|
||
| const jsonSchema: unknown = { | ||
| type: "object", | ||
| properties: Object.keys(schema).reduce( | ||
| (acc: Record<string, unknown>, key) => { | ||
| const schemaValue = schema[key as keyof Schema]; | ||
| acc[key] = { type: (schemaValue as any)?.type || typeof schemaValue }; | ||
| return acc; | ||
| }, | ||
| {}, | ||
| ), | ||
| required: Object.keys(schema), | ||
| additionalProperties: true, | ||
| }; | ||
|
|
||
| const rootResult = validator.validate(data, jsonSchema as Schema); | ||
| if (rootResult.valid) { | ||
| return true; | ||
| } | ||
|
|
||
| function checkSubtrees(obj: unknown): boolean { | ||
| if (typeof obj !== "object" || obj === null) { | ||
| return false; | ||
| } | ||
|
|
||
| if (Array.isArray(obj)) { | ||
| return obj.some((item) => checkSubtrees(item)); | ||
| } | ||
|
|
||
| const result = validator.validate(obj, jsonSchema as Schema); | ||
| if (result.valid) { | ||
| return true; | ||
| } | ||
|
|
||
| return Object.values(obj).some((value) => checkSubtrees(value)); | ||
| } | ||
|
|
||
| return checkSubtrees(data); | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just a heads up, I already have some fancy logging stuff using
pino-loggerhttps://github.com/pinojs/pinoIt's currently only hooked up to hono via a middleware, and not super obvious how to use elsewhere: https://github.com/commontoolsinc/labs/blob/main/typescript/packages/toolshed/middlewares/pino-logger.ts
I'm cool merging this as-is, but I'll probably make a follow-up pass at killing pino or this setup in the next week or two.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
SGTM! I would prefer to use a library, I was just losing my sanity without context in the logs. Let's rip it out soon 👍