Skip to content

Commit

Permalink
track improvements
Browse files Browse the repository at this point in the history
  • Loading branch information
alex-dixon committed Oct 3, 2024
1 parent 39bcf1f commit 6fb8fc2
Show file tree
Hide file tree
Showing 4 changed files with 38 additions and 11 deletions.
3 changes: 1 addition & 2 deletions typescript/examples/output_parsing.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ const MovieReview = z.object({
const generateMovieReview = ell.complex({
model: "gpt-4o-mini",
response_format: MovieReview ,
exempt_from_tracking: true
}, async (movie: string) => {
return [
ell.system("You are a movie review generator. Given the name of a movie, you need to return a structured review."),
Expand All @@ -24,8 +23,8 @@ const generateMovieReview = ell.complex({
ell.init({ store: './logdir', autocommit: true, verbose: true })

const reviewMessage = await generateMovieReview("The Matrix")
console.log(reviewMessage)
const review = reviewMessage.parsed
review.rating.toExponential()

console.log(`Movie: ${review.title}, Rating: ${review.rating}/10`)
console.log(`Summary: ${review.summary}`)
Expand Down
25 changes: 19 additions & 6 deletions typescript/src/lmp/_track.ts
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ const lmpTypeFromDefinitionType = (definitionType: LMPDefinitionType) => {

/**
* Invokes the LMP with tracking.
* @param lmp I
* @param lmp
* @param args
* @param f
* @param a
Expand Down Expand Up @@ -152,7 +152,7 @@ export const invokeWithTracking = async (lmp: LMPDefinition & { lmpId: string },
//
// We get strange behavior if a breakpoint is set to a line that isn't one of the "blessed" possible breakpoint lines
// (the program exits with code 0 unexpectedly)
// So we try to find the closest one
// So we try to find the closest one to the ending return statement of the LMP
let bestBreakpoint = await getBestClosureInspectionBreakpoint(session, location.scriptId, {
line: generatedPositionStart.line,
endLine: generatedPositionEnd.line,
Expand Down Expand Up @@ -188,14 +188,26 @@ export const invokeWithTracking = async (lmp: LMPDefinition & { lmpId: string },
})

const handleBreakpointHit = async ({ params }: { params: inspector.Debugger.PausedEventDataType }) => {
// TODO. For performance we should aggressively filter the breakpoints we set.
// This function runs whenever the debugger pauses, including a user's "step-into/step-over" etc.
// When using "step into/out/over", hitBreakpoints is empty
if (!params.hitBreakpoints || params.hitBreakpoints.length === 0) {
return
}
logger.debug('Paused on breakpoint', {
breakpoints: params.hitBreakpoints,
// params: JSON.stringify(params, null, 2)
})
const { callFrames } = params
const scopes = callFrames[0].scopeChain

// Get the variables you're interested in
// Get the variables we're interested in
//
// TODO. Once we have clarified what is needed for free vars vs global vars
// we should be able to get everything we need here, potentially from scope.type === 'global' in addition to these
// There is additional line information on the scope that is available for us to use
// for checking we're in the right spot.
// For now we expect to do this work when we set breakpoints in the first place
for (const scope of scopes) {
if (scope.type === 'closure') {
const result = (await session
Expand Down Expand Up @@ -244,8 +256,9 @@ export const invokeWithTracking = async (lmp: LMPDefinition & { lmpId: string },
}
}

// By this time we assume we captured all variables of interest
session.off('Debugger.paused', handleBreakpointHit)

resolve(undefined)
}

Expand Down Expand Up @@ -279,7 +292,7 @@ export const invokeWithTracking = async (lmp: LMPDefinition & { lmpId: string },
// todo. find what these refer to exactly
initial_free_vars: {},
initial_global_vars: {},
// todo. requires static analysis of direct children of this lmp definition
// todo. requires static analysis of direct children of this lmp definition?
uses: [],
})
} catch (e) {
Expand Down Expand Up @@ -352,7 +365,7 @@ export const invokeWithTracking = async (lmp: LMPDefinition & { lmpId: string },
state_cache_key: '',
consumes: [],
})
return result
return result.length === 1 ? result[0] : result
}
)
}
2 changes: 1 addition & 1 deletion typescript/src/serialize/sql.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import * as sqlite3 from 'sqlite3'
import { open, Database } from 'sqlite'
import { LMPType } from '../lmp/types'
import * as logging from '../util/_logging'
import { ISODateString } from './types'
import { ISODateString, WriteInvocationInput, WriteLMPInput } from './types'

const logger = logging.getLogger('sql')
const gzip = promisify(zlib.gzip)
Expand Down
19 changes: 17 additions & 2 deletions typescript/src/util/closure.ts
Original file line number Diff line number Diff line change
Expand Up @@ -104,10 +104,10 @@ export async function getBestClosureInspectionBreakpoint(
},
end: {
scriptId,
// this helps single line functions
lineNumber: location.endLine + 1,
lineNumber: location.line === location.endLine ? location.line + 1 : location.endLine,
},
})

if (!possibleBreakpoints.locations || possibleBreakpoints.locations.length === 0) {
return null
}
Expand All @@ -119,6 +119,21 @@ export async function getBestClosureInspectionBreakpoint(
logger.debug('Using return breakpoint', { lastBreakpoint })
return lastBreakpoint
}
// This is the best heuristic we have atm. Alternatives that may be more reliable:
// - retrive the return position from typescript ast, get the source mapped position of that, then find the closest available breakpoint to that location here.
// Note: When we always add 1 to the range above, v8 gives us
// a breakpoint that is column 0 and of `type: undefined` and a line past function's return statement.
// This causes some silent crash and should probably be reported to nodejs.
// We may want to avoid that situation in all cases by only using a return breakpoint.
const secondLastBreakpoint = possibleBreakpoints.locations[possibleBreakpoints.locations.length - 2]
if (secondLastBreakpoint.type === 'return') {
logger.debug('Last breakpoint not a return. Using second last breakpoint (return)', {
secondLastBreakpoint,
lastBreakpoint,
})
return secondLastBreakpoint
}
logger.debug('No return breakpoint seemed safe. Using last breakpoint', { lastBreakpoint })
// use the last one regardless until we have a better idea
return lastBreakpoint
}

0 comments on commit 6fb8fc2

Please sign in to comment.